/*
 * Copyright (c) 2018 - 2028. www.vtuzx.com Inc. All Rights Reserved
 */
package com.vtuzx.kingdee.xqc_api.service.impl;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.vtuzx.core.VtuzxException;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.bean.dto.VtuzxPage;
import com.vtuzx.core.bean.dto.VtuzxToken;
import com.vtuzx.core.constant.IVtuzxConst;
import com.vtuzx.core.file.excel.VtuzxExcel;
import com.vtuzx.core.file.excel.VtuzxExcelCell;
import com.vtuzx.core.file.excel.VtuzxExcelRow;
import com.vtuzx.core.file.excel.VtuzxExcelSheet;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.fast.service.IFastSettingService;
import com.vtuzx.fast.utils.FastUtil;
import com.vtuzx.kingdee.xqc_api.service.IXqcConfigService;
import com.vtuzx.kingdee.xqc_api.service.IXqcInventoryService;
import com.vtuzx.kingdee.xqc_api.service.IXqcProduceService;
import com.vtuzx.kingdee.xqc_api.service.IXqcSyncKingdeeOrderService;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import com.vtuzx.kingdee.xqc_core.bean.kingdee.VtuzxKingdeeCloudClient;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterial;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterialBox;
import com.vtuzx.kingdee.xqc_core.constant.BillEvent;
import com.vtuzx.kingdee.xqc_core.constant.BillStatus;
import com.vtuzx.kingdee.xqc_core.constant.BillType;
import com.vtuzx.kingdee.xqc_core.constant.IXqcConst;
import com.vtuzx.kingdee.xqc_core.dao.*;
import com.vtuzx.kingdee.xqc_core.service.IJiKeYunApiService;
import com.vtuzx.kingdee.xqc_core.service.IVtuzxKingdeeService;
import com.vtuzx.web.bean.VtuzxDownloadBean;
import com.vtuzx.web.dao.mongo.CustomerDao;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 采购服务
 */
@Service
public class XqcProduceServiceImpl implements IXqcProduceService {
    @Autowired
    private PrdInDao prdInDao;

    /**
     * 金蝶
     */
    @Autowired
    private IVtuzxKingdeeService kingdeeService;

    @Autowired
    private PrdInDetailDao prdInDetailDao;

    @Autowired
    private StockDao stockDao;

    @Autowired
    private XqcOtherOutServiceImpl otherOutService;

    @Autowired
    private PrdInDetailBoxDao prdInDetailBoxDao;

    @Autowired
    private InventoryDetailDao inventoryDetailDao;

    @Autowired
    private InventoryDao inventoryDao;

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private PrdColDao prdColDao;

    @Autowired
    private PrdColDetailDao prdColDetailDao;

    @Autowired
    private PrdPickDao prdPickDao;

    @Autowired
    private PrdPickDetailDao prdPickDetailDao;

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private PrdPickDetailBoxDao prdPickDetailBoxDao;

    @Autowired
    private IXqcInventoryService inventoryService;

    @Autowired
    private IXqcConfigService configService;

    @Autowired
    private XqcInventoryServiceImpl xqcInventoryService;

    @Autowired
    private SupplierDao supplierDao;

    @Autowired
    private PrdTaskDao prdTaskDao;

    @Autowired
    private PrdTaskDetailDao prdTaskDetailDao;

    @Autowired
    private MaterialBomDao materialBomDao;

    @Autowired
    private MaterialBomDetailDao materialBomDetailDao;

    @Autowired
    private BomDao bomDao;

    @Autowired
    private MaterialBomPickDao materialBomPickDao;

    @Autowired
    private MaterialBomPickDetailDao materialBomPickDetailDao;

    @Autowired
    private MaterialBomPickDetailBoxDao materialBomPickDetailBoxDao;

    @Autowired
    private MaterialBomSupplementDao materialBomSupplementDao;

    @Autowired
    private MaterialBomSupplementDetailDao materialBomSupplementDetailDao;

    @Autowired
    private MaterialBomSupplementDetailBoxDao materialBomSupplementDetailBoxDao;

    @Autowired
    private MaterialBomReturnDao materialBomReturnDao;

    @Autowired
    private MaterialBomReturnDetailDao materialBomReturnDetailDao;

    @Autowired
    private MaterialBomReturnDetailBoxDao materialBomReturnDetailBoxDao;

    @Autowired
    private TraceabilityCodeDao traceabilityCodeDao;

    @Autowired
    private TraceabilityCodeDetailDao traceabilityCodeDetailDao;

    @Autowired
    private OtherOutDao otherOutDao;

    @Autowired
    private OtherOutDetailDao otherOutDetailDao;

    @Autowired
    private OtherOutDetailBoxDao otherOutDetailBoxDao;

    @Autowired
    private IXqcSyncKingdeeOrderService syncKingdeeOrderService;

    @Autowired
    IFastSettingService settingService;

    @Autowired
    private DesaltingInStockDao desaltingInStockDao;

    @Autowired
    private DesaltingInStockDetailDao desaltingInStockDetailDao;

    @Autowired
    private DesaltingInStockDetailBoxDao desaltingInStockDetailBoxDao;

    @Autowired
    private IXqcProduceService produceService;

    @Autowired
    private PurColDetailDao purColDetailDao;

    @Autowired
    private PurColDao purColDao;

    @Autowired
    private OtherColDao otherColDao;

    @Autowired
    private OtherColDetailDao otherColDetailDao;

    @Autowired
    private IJiKeYunApiService iJiKeYunApiService;

    @Autowired
    private StoreTokenDao storeTokenDao;

    /**
     * Logger
     */
    private static final Logger _logger = LoggerFactory.getLogger(XqcProduceServiceImpl.class);

    @Override
    public void bindPrdColBoxRfid(String boxNo, String rfid) throws VtuzxException {
        Document boxDoc = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo).and("inStock").ne(true));
        if (boxDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String billNo = VtuzxUtil.getString(boxDoc, "billNo");
        Document prdColDoc = prdColDao.findOne(Criteria.where("billNo").is(billNo));
        if (prdColDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String status = VtuzxUtil.getString(prdColDoc, "status");
        if (!BillStatus.Audit.hit(status)) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_audit, boxNo);
        }
        Criteria lastPrdColBindRfid = Criteria.where("rfid").is(rfid).and("inStock").ne(true);
        Document lastPrdColDetail = prdColDetailDao.findOne(lastPrdColBindRfid);
        if (lastPrdColDetail != null) {
            prdColDetailDao.updateByIdRedirect(lastPrdColDetail.getObjectId(IVtuzxConst.Key__id), new Document("$unset", new Document("rfid", 1)));
            prdColDao.updateOneRedirect(Criteria.where("billNo").is(VtuzxUtil.getString(lastPrdColDetail, "billNo")), new Document("$inc", new Document("bindBoxCount", -1)));
        }
        prdColDetailDao.updateById(boxDoc.getObjectId(IVtuzxConst.Key__id), new Document("rfid", rfid));
        if (VtuzxUtil.isEmpty(VtuzxUtil.getString(boxDoc, "rfid"))) {
            prdColDao.updateByIdRedirect(prdColDoc.getObjectId(IVtuzxConst.Key__id), new Document("$inc", new Document("bindBoxCount", 1)));
        }
    }

    @Override
    public VtuzxMap getPrdColMaterialForBind(String boxNo) throws VtuzxException {
        Document boxDoc = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));
        if (boxDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        boolean inStock = VtuzxUtil.getBoolean(boxDoc, "inStock");
        if (inStock) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_in_stock, boxNo);
        }
        String billNo = VtuzxUtil.getString(boxDoc, "billNo");
        Document prdColDoc = prdColDao.findOne(Criteria.where("billNo").is(billNo));
        if (prdColDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String status = VtuzxUtil.getString(prdColDoc, "status");
        if (!BillStatus.Audit.hit(status)) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_audit, boxNo);
        }
        return new VtuzxMap("materialNo", VtuzxUtil.getString(prdColDoc, "materialNo"))
                .append("materialName", VtuzxUtil.getString(prdColDoc, "materialName"))
                .append("materialSpec", VtuzxUtil.getString(prdColDoc, "materialSpec"))
                .append("batchNo", VtuzxUtil.getString(prdColDoc, "batchNo"))
                .append("unit", VtuzxUtil.getString(prdColDoc, "unit"))
                .append("count", VtuzxUtil.getDouble(boxDoc, "count"))
                .append("supplierName", VtuzxUtil.getString(prdColDoc, "supplierName"))
                .append("instockDate", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdColDoc, "createTime")))
                .append("produceDate", VtuzxUtil.getString(prdColDoc, "produceDate"))
                .append("exp", VtuzxUtil.getInt(prdColDoc, "exp"));
    }

    @Override
    public VtuzxMap saveUserPrdPick(ObjectId _userId, String userName, Map<String, Object> param) throws VtuzxException {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String billNo = IXqcConst.createBillNo(BillType.SCLL);
        List<String> boxNoList = new ArrayList<>();
        List<String> materialRowIdList = new ArrayList<>();
        List<ObjectId> detailIdList = new ArrayList<>();
        Criteria opCond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        Iterator<Document> detailItr = prdPickDetailDao.findList(opCond, null, 0, 0);
        int boxCount = 0;
        double count = 0d;
        while (detailItr.hasNext()) {
            Document detail = detailItr.next();
            ObjectId id = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
            boxCount += VtuzxUtil.getInt(detail, "boxCount");
            count += VtuzxUtil.getDouble(detail, "count");
            detailIdList.add(id);
        }

        VtuzxMap boxIdMap = new VtuzxMap();
        Iterator<Document> boxItr = prdPickDetailBoxDao.findList(Criteria.where("_detailId").in(detailIdList), null, 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
            String id = VtuzxUtil.getString(boxDoc, "_detailId");
            boxNoList.add(boxNo);
            boxIdMap.append(boxNo, id);
        }

        List<String> outBoxNoList = new ArrayList<>();
        Iterator<Document> inventoryItr = inventoryDetailDao.findList(Criteria.where("boxNo").in(boxNoList).and("status").is("in"), null, 0, 0);
        while (inventoryItr.hasNext()) {
            Document inventoryDoc = inventoryItr.next();
            String status = VtuzxUtil.getString(inventoryDoc, "status");
            String boxNo = VtuzxUtil.getString(inventoryDoc, "boxNo");
            if ("out".equals(status)) {
                outBoxNoList.add(boxNo);
                String detailId = VtuzxUtil.getString(boxIdMap, boxNo);
                materialRowIdList.add(detailId);
            }
        }
        if (outBoxNoList.size() > 0) {
            return new VtuzxMap("outBoxNo", outBoxNoList).append("idList", materialRowIdList);
        }

        Document prdPickDoc = new Document("billNo", billNo)
                .append("stockNo", stockNo)
                .append("boxCount", boxCount)
                .append("count", count)
                .append("status", BillStatus.Save.toString());
        prdPickDao.insertBill(_userId, userName, prdPickDoc);
        try {
            Document detailUpdateVal = new Document("$set", new Document("billNo", billNo));
            detailUpdateVal.append("$unset", new Document("isTemp", 1));
            prdPickDetailDao.updateManyRedirect(opCond, detailUpdateVal);
            prdPickDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
            auditPrdPickOrder(_userId, userName, stockNo, billNo);
        } catch (Exception e) {
            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            prdPickDao.deleteOne(rollbackCond);
            prdPickDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            prdPickDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            throw e;
        }
        return new VtuzxMap("outBoxNo", outBoxNoList);
    }


    /**
     * 生产领料审批
     *
     * @param _userId  用户ID
     * @param userName 用户名
     * @param stockNo  仓库编码
     * @param billNo   单据号
     * @throws VtuzxException 异常处理
     */
    public void auditPrdPickOrder(ObjectId _userId, String userName, String stockNo, String billNo) throws VtuzxException {
        Criteria getCond = Criteria.where("billNo").is(billNo);
        Iterator<Document> prdPickDetailBoxItr = prdPickDetailBoxDao.findList(getCond, null, 0, 0);
        List<String> boxNoList = new ArrayList<>();
        List<Document> zsBoxList = new ArrayList<>();
        List<VtuzxMap> bcBoxList = new ArrayList<>();
        while (prdPickDetailBoxItr.hasNext()) {
            Document doc = prdPickDetailBoxItr.next();
            boolean isZS = VtuzxUtil.getBoolean(doc, "isZS");
            String traceBack = VtuzxUtil.getString(doc, "traceBack");
            String barcodeType = VtuzxUtil.getString(doc, "barcodeType");
            if ("BC".equals(barcodeType)) {
                bcBoxList.add(new VtuzxMap("boxNo", VtuzxUtil.getString(doc, "boxNo"))
                        .append("count", BigDecimal.valueOf(VtuzxUtil.getDouble(doc, "count")).setScale(0, RoundingMode.HALF_UP).intValue())
                        .append("locationNo", VtuzxUtil.getString(doc, "locationNo")));
            } else {
                if (isZS) {
                    zsBoxList.add(new Document("traceBack", traceBack).append("boxNo", VtuzxUtil.getString(doc, "boxNo")));
                } else {
                    boxNoList.add(VtuzxUtil.getString(doc, "boxNo"));
                }

            }
        }
        prdPickDao.audit(_userId, userName, billNo);
        // 更新即时库存
        try {
            inventoryService.reduceInventory(_userId, userName, BillEvent.Audit, BillType.SCLL, stockNo, billNo, boxNoList, bcBoxList, zsBoxList);
        } catch (Exception e) {
            prdPickDao.unaudit(billNo);
            throw e;
        }
    }

    @Override
    public Object addUserPrdPickMaterialBoxList(ObjectId _userId, String name, String stockNo, List<Map<String, Object>> boxList) throws VtuzxException {
        List<VtuzxMap> boxNoDateList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        for (Map<String, Object> box : boxList) {
            boxNoList.add(VtuzxUtil.getString(box, "boxNo"));
        }
        Iterator<Document> scanBoxDocItr = prdPickDetailBoxDao.findList(Criteria.where("boxNo").in(boxNoList).and("isTemp").is(true), null, 0, 0);
        while (scanBoxDocItr.hasNext()) {
            Document scanDoc = scanBoxDocItr.next();
            String boxNo = VtuzxUtil.getString(scanDoc, "boxNo");
            String createUserName = VtuzxUtil.getString(scanDoc, "createUserName");
            boxNoDateList.add(new VtuzxMap(boxNo, createUserName));
        }
        if (boxNoDateList.size() != 0) {
            throw new VtuzxException("托盘中箱号已添加，请删除后重新扫描!【" + boxNoDateList.toString() + "】");
        }

        for (Map<String, Object> box : boxList) {
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            String locationNo = VtuzxUtil.getString(box, "locationNo");
            String traceBack = VtuzxUtil.getString(box, "traceBack");
            boolean isZS = VtuzxUtil.getBoolean(box, "isZS");
            int count = VtuzxUtil.getInt(box, "count");
            try {
                VtuzxMap xqcProduceDetail = xqcInventoryService.getMaterialBox(stockNo, locationNo, boxNo);
                List<VtuzxMap> dataList = VtuzxUtil.getObject(xqcProduceDetail, "data");
                for (VtuzxMap data : dataList) {
                    addUserPrdPickMaterialBoxInner(data, _userId, name, stockNo, boxNo, count, traceBack, isZS);
                }
            } catch (Exception e) {
//                _logger.info("addUserPrdPickMaterialBoxList error:" + e.getMessage());
                throw new VtuzxException(e.getMessage());
            }
        }
        return null;
    }

    @Override
    public VtuzxMap addUserPrdPickMaterialBox(ObjectId _userId, String userName, String stockNo, String boxNo, int count) throws VtuzxException {
        VtuzxMap xqcProduceDetail = xqcInventoryService.getMaterialBox(stockNo, boxNo);
        ObjectId _detailId = addUserPrdPickMaterialBoxInner(xqcProduceDetail, _userId, userName, stockNo, boxNo, count, "", false);
        Document prdPickDetailDoc = prdPickDetailDao.findById(_detailId);
        return new VtuzxMap("boxCount", VtuzxUtil.getObject(prdPickDetailDoc, "boxCount"))
                .append("count", VtuzxUtil.getObject(prdPickDetailDoc, "count"));
    }

    private ObjectId addUserPrdPickMaterialBoxInner(VtuzxMap xqcProduceDetail, ObjectId _userId, String userName, String stockNo, String boxNoKey, int inputCount, String traceBack, boolean isZS) throws VtuzxException {
        String barcodeType = VtuzxUtil.getString(xqcProduceDetail, "barcodeType");
        String materialNo = VtuzxUtil.getString(xqcProduceDetail, "materialNo");
        double count = inputCount;
        String boxNo;
        if ("BC".equals(barcodeType)) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 5) {
                boxNo = boxNoKey;
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo + "|;batch";
            } else {
                boxNo = boxNoKey;
            }
        } else {
            boxNo = boxNoKey;
            count = VtuzxUtil.getDouble(xqcProduceDetail, "count");
//            Document scanBoxDoc = prdPickDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
//            if (scanBoxDoc != null) {
//                throw new VtuzxException("箱号已领料!");
//            }
        }

        Criteria pickCond = new Criteria("boxNo").is(boxNo).and("isTemp").is(true);
        if (isZS) {
            pickCond.and("traceBack").is(traceBack);
        }
        Document scanBoxDoc = prdPickDetailBoxDao.findOne(pickCond);
        if (scanBoxDoc != null) {
            String createUserName = VtuzxUtil.getString(scanBoxDoc, "createUserName");
            throw new VtuzxException("箱号已领料，请勿重复添加!【扫描人:" + createUserName + "】");
        }

        String materialNumber = VtuzxUtil.getString(xqcProduceDetail, "materialNo");
        String materialName = VtuzxUtil.getString(xqcProduceDetail, "materialName");
        String materialSpec = VtuzxUtil.getString(xqcProduceDetail, "materialSpec");
        String batchNo = VtuzxUtil.getString(xqcProduceDetail, "batchNo");
        String locationNo = VtuzxUtil.getString(xqcProduceDetail, "locationNo");
        String unit = VtuzxUtil.getString(xqcProduceDetail, "unit");
        String produceDate = VtuzxUtil.getString(xqcProduceDetail, "produceDate");
        double exp = VtuzxUtil.getDouble(xqcProduceDetail, "exp");
        String inStockTime = VtuzxUtil.getString(xqcProduceDetail, "inStockTime");
        Criteria detailCond = Criteria.where("_createUserId").is(_userId);
        detailCond.and("isTemp").is(true);
        detailCond.and("stockNo").is(stockNo);
        detailCond.and("materialNo").is(materialNo);
        detailCond.and("batchNo").is(batchNo);
        detailCond.and("unit").is(unit);
        Document detail = prdPickDetailDao.findOne(detailCond);
        Document updateVal = new Document();

        if (detail == null) {
            updateVal.append("isTemp", true);
            updateVal.append("stockNo", stockNo);
            updateVal.append("materialNo", materialNumber);
            updateVal.append("materialName", materialName);
            updateVal.append("materialSpec", materialSpec);
            updateVal.append("batchNo", batchNo);
            updateVal.append("unit", unit);
            updateVal.append("_createUserId", _userId);
            updateVal.append("createUserName", userName);
            updateVal.append("boxCount", 1);
            if (isZS) {
                updateVal.append("count", 1);
            } else {
                updateVal.append("count", count);
            }
            updateVal.append("produceDate", produceDate);
            updateVal.append("exp", exp);
            updateVal.append("inStockTime", inStockTime);
        } else {
            if (isZS) {
                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", 1));
            } else {
                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
            }

        }
        ObjectId _detailId;
        if (detail == null) {
            _detailId = prdPickDetailDao.insertOne(updateVal);
        } else {
            _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
            prdPickDetailDao.updateByIdRedirect(_detailId, updateVal);
        }
        Document detailBox = new Document();
        detailBox.append("isTemp", true);
        detailBox.append("_detailId", _detailId);
        detailBox.append("boxNo", boxNo);
        detailBox.append("barcodeType", barcodeType);
        detailBox.append("_createUserId", _userId);
        detailBox.append("createUserName", userName);
        detailBox.append("stockNo", stockNo);
        detailBox.append("unit", unit);
        detailBox.append("locationNo", locationNo);
        if (isZS) {
            detailBox.append("traceBack", traceBack);
            detailBox.append("isZS", true);
            detailBox.append("count", 1);
        } else {
            detailBox.append("count", count);
        }
        prdPickDetailBoxDao.insertOne(detailBox);

        return _detailId;
    }

    @Override
    public VtuzxMap deleteUserPrdPickMaterialBox(ObjectId _userId, String id) {
        Document prdPickDetailBoxDoc = prdPickDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(prdPickDetailBoxDoc, "_detailId");
        prdPickDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> prdPickDetailBoxItr = prdPickDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (prdPickDetailBoxItr.hasNext()) {
            Document doc = prdPickDetailBoxItr.next();
            double prdPickDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = prdPickDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0 && total == 0) {
            prdPickDetailDao.deleteById(_detailId);
        } else {
            prdPickDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public void deleteUserPrdPickMaterial(ObjectId _userId, String id) {
        prdPickDetailDao.deleteById(FastUtil.convertId(id));
        prdPickDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserPrdPick(ObjectId _userId, String stockNo) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        prdPickDetailDao.deleteMany(cond);
        prdPickDetailBoxDao.deleteMany(cond);
    }

    @Override
    public VtuzxMap updateUserPrdPickMaterialBox(ObjectId _userId, String stockNo, String materialNo, String boxNo, double count) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("boxNo").is(boxNo).and("isTemp").is(true);
        Document detailBoxDoc = prdPickDetailBoxDao.findOne(cond);
        ObjectId _detailId = VtuzxUtil.getObject(detailBoxDoc, "_detailId");
        prdPickDetailBoxDao.updateOne(cond, new Document("count", count));
        Iterator<Document> prdPickDetailBoxItr = prdPickDetailBoxDao.findList(Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true), new Document("stockNo", 1), 0, 0);
        int boxCount = 0;
        double total = 0;
        while (prdPickDetailBoxItr.hasNext()) {
            Document doc = prdPickDetailBoxItr.next();
            double prdPickDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = prdPickDetailBoxCount + total;
            boxCount++;
        }
        prdPickDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public VtuzxMap getUserPrdPickMaterial(ObjectId _userId, String stockNo) {
        List<VtuzxMap> prdPickDetailList = new ArrayList<>();
        Iterator<Document> prdPickDetailItr = prdPickDetailDao.findList(Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true), null, 0, 0);
        while (prdPickDetailItr.hasNext()) {
            Document prdPickDetailDoc = prdPickDetailItr.next();
            VtuzxMap prdPickDetailMap = new VtuzxMap(prdPickDetailDoc);
            String id = VtuzxUtil.removeString(prdPickDetailMap, IVtuzxConst.Key__id);
            String createUserId = VtuzxUtil.removeString(prdPickDetailMap, "_createUserId");
            prdPickDetailMap.append("id", id).append("createUserId", createUserId);
            prdPickDetailList.add(prdPickDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, prdPickDetailList);
    }

    @Override
    public VtuzxMap getUserPrdPickMaterialBox(ObjectId _userId, String _detailId) {
        List<VtuzxMap> prdPickDetailBoxList = new ArrayList<>();
        Iterator<Document> prdPickDetailBoxItr = prdPickDetailBoxDao.findList(Criteria.where("_createUserId").is(_userId).and("_detailId").is(new ObjectId(_detailId)), null, 0, 0);
        while (prdPickDetailBoxItr.hasNext()) {
            Document prdPickDetailBoxDoc = prdPickDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(prdPickDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            prdPickDetailBoxList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, prdPickDetailBoxList);
    }

    @Override
    public VtuzxMap getPrdPickBill(ObjectId _userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        List<String> auditTime = VtuzxUtil.getObject(param, "auditTime");
        List<VtuzxMap> dataList = new ArrayList<>();
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").regex(stockNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(auditTime)) {
            cond.and("auditTime").gte(VtuzxUtil.parseDate(auditTime.get(0))).lte(VtuzxUtil.parseDate(auditTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo) || !VtuzxUtil.isEmpty(boxNo)) {
            List<String> inBillNoList = new ArrayList<>();
            if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) {
                Criteria smallCond = new Criteria();
                if (!VtuzxUtil.isEmpty(materialNo)) {
                    smallCond.and("materialNo").is(materialNo);
                }
                if (!VtuzxUtil.isEmpty(batchNo)) {
                    smallCond.and("batchNo").regex(batchNo);
                }
                Iterator<Document> purInDetailItr = prdPickDetailDao.findList(smallCond, null, 0, 0);
                while (purInDetailItr.hasNext()) {
                    Document purInDetailDoc = purInDetailItr.next();
                    String purInBillNo = VtuzxUtil.getString(purInDetailDoc, "billNo");
                    inBillNoList.add(purInBillNo);
                }
            } else {
                Iterator<Document> boxItr = prdPickDetailBoxDao.findList(Criteria.where("boxNo").is(boxNo), null, 0, 0);
                while (boxItr.hasNext()) {
                    Document boxDoc = boxItr.next();
                    inBillNoList.add(VtuzxUtil.getString(boxDoc, "billNo"));
                }
            }

            Iterator<Document> purInItr = prdPickDao.findList(Criteria.where("billNo").in(inBillNoList), null, 0, 0);
            while (purInItr.hasNext()) {
                Document purInDoc = purInItr.next();
                VtuzxMap purInMap = new VtuzxMap(purInDoc);
                purInMap.append("id", VtuzxUtil.removeString(purInMap, IVtuzxConst.Key__id));
                purInMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInMap, "createTime")));
                dataList.add(purInMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_data, dataList);
        }
        VtuzxPage page = prdPickDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "auditTime")))
                .append("count", VtuzxUtil.getDouble(doc, "count")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdPickBillDetail(ObjectId _userId, String stockNo, String billNo) {
        Document prdPickDoc = prdPickDao.findOne(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo));
        String scllBillNo = VtuzxUtil.getString(prdPickDoc, "billNo");
        String createUserName = VtuzxUtil.getString(prdPickDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPickDoc, "createTime"));
        String stock = VtuzxUtil.getString(prdPickDoc, "stockNo");
        double count = VtuzxUtil.getDouble(prdPickDoc, "count");
        int boxCount = VtuzxUtil.getInt(prdPickDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scllBillNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("stockNo", stock)
                .append("count", count)
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdPickDetailItr = prdPickDetailDao.findList(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo), null, 0, 0);
        while (prdPickDetailItr.hasNext()) {
            Document prdPickDetailDoc = prdPickDetailItr.next();
            VtuzxMap prdPickDetailMap = new VtuzxMap(prdPickDetailDoc);
            String materialNo = VtuzxUtil.getString(prdPickDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(prdPickDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(prdPickDetailMap, "_createUserId");

            prdPickDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(prdPickDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdPickBillDetailBox(ObjectId _userId, String _detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(_detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdPickDetailBoxItr = prdPickDetailBoxDao.findList(cond, null, 0, 0);
        while (prdPickDetailBoxItr.hasNext()) {
            Document prdPickDetailBoxDoc = prdPickDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(prdPickDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void saveUserPrdInByPrdColList(ObjectId _userId, String userName, String stockNo, String locationNo, List<String> billNoList) throws Exception {
        List<ObjectId> _detailIdList = new ArrayList<>();
        List<String> taskBillNoList = new ArrayList<>();
        //入库之前添加一个判断,如果当期用户有临时数据的话不允许入库
        long count1 = prdInDetailBoxDao.count(Criteria.where("_createUserId").is(_userId).and("isTemp").is(true));
        if (count1 > 0) {
            throw new VtuzxException("存在未入完库的情况,请稍后再试");
        }
        try {
            //查询车间收货外层表信息
            Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
            //key : 车间收货单号 val:
            VtuzxMap prdColMap = new VtuzxMap();
            while (prdColItr.hasNext()) {
                Document prdColDoc = prdColItr.next();
                String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
                if (VtuzxUtil.isEmpty(taskBillNo)) {
                    throw new VtuzxException("存在未关联生产任务的单据，不能进行批量入库");
                }
                if (!taskBillNoList.contains(taskBillNo)) {
                    taskBillNoList.add(taskBillNo);
                }
                prdColDoc.append("countTotal", VtuzxUtil.removeObject(prdColDoc, "count"));
                if (BillStatus.Audit.hit(VtuzxUtil.getString(prdColDoc, "status"))) {
                    String prdColBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                    prdColMap.append(prdColBillNo, prdColDoc);
                }
            }
            Iterator<Document> prdColBoxItr = prdColDetailDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
            while (prdColBoxItr.hasNext()) {
                Document prdColBoxDoc = prdColBoxItr.next();
                boolean inStock = VtuzxUtil.getBoolean(prdColBoxDoc, "inStock");
                if (inStock) {
                    continue;
                }
                String prdColBoxBillNo = VtuzxUtil.getString(prdColBoxDoc, "billNo");
                Document prdColDoc = VtuzxUtil.getObject(prdColMap, prdColBoxBillNo);
                if (prdColDoc == null) {
                    continue;
                }
                String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
                VtuzxMap detailBoxMap = new VtuzxMap(prdColBoxDoc);
                detailBoxMap.putAll(prdColDoc);
                detailBoxMap.remove(IVtuzxConst.Key__id);
                detailBoxMap.remove(IVtuzxConst.Key_createTime);
                detailBoxMap.remove(IVtuzxConst.Key_updateTime);
                detailBoxMap.remove("auditTime");
                detailBoxMap.remove("_createUserId");
                detailBoxMap.remove("_updateUserId");
                detailBoxMap.remove("createUserName");
                detailBoxMap.remove("updateUserName");
                detailBoxMap.remove("auditUserName");
                String boxNo = VtuzxUtil.getString(detailBoxMap, "boxNo");
                double count = VtuzxUtil.getDouble(detailBoxMap, "count");
                ObjectId _detailId = addUserPrdInMaterialBoxInner(detailBoxMap, _userId, userName, stockNo, locationNo, boxNo, count, true, taskBillNo);
                FastUtil.addToIdList(_detailIdList, _detailId);
            }
            // 一次审批
//            saveUserPrdIn(_userId, userName, stockNo);
            for (String taskBillNo : taskBillNoList) {
                produceService.createPrdInBill(_userId, userName, taskBillNo, stockNo);
            }
        } catch (Exception e) {
            if (!VtuzxUtil.isEmpty(_detailIdList)) {
                prdInDetailDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(_detailIdList));
                prdInDetailBoxDao.deleteMany(Criteria.where("_detailId").in(_detailIdList));
            }
            throw e;
        }
    }

    @Override
    public void saveUserPrdIn(ObjectId _userId, String userName, String stockNo) throws Exception {
        // 加人，时间，仓库，总箱数，总重量
        boolean returnType = false;
        boolean desaltingType = false;
        VtuzxMap dataMap = new VtuzxMap();//key任务号,val:入库数量和箱号数量
        Criteria opCond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        Iterator<Document> detailItr = prdInDetailBoxDao.findList(opCond, null, 0, 0);
        while (detailItr.hasNext()) {
            Document detail = detailItr.next();
            boolean returnCol = VtuzxUtil.getBoolean(detail, "return");
            boolean desalting = VtuzxUtil.getBoolean(detail, "desalting");
            String taskBillNo = VtuzxUtil.getString(detail, "taskBillNo");
            double count = VtuzxUtil.getDouble(detail, "count");
            VtuzxMap countData = VtuzxUtil.getObject(dataMap, taskBillNo);
            if (VtuzxUtil.isEmpty(countData)) {
                dataMap.append(taskBillNo, new VtuzxMap("count", count).append("boxCount", 1));
            } else {
                countData.append("count", count + VtuzxUtil.getDouble(countData, "count")).append("boxCount", VtuzxUtil.getInt(countData, "boxCount") + 1);
            }
            if (returnCol) {
                returnType = true;
            }
            if (desalting) {
                desaltingType = true;
            }
        }
        boolean finalReturnType = returnType;
        boolean finalDesaltingType = desaltingType;
        dataMap.forEach((k, v) -> {
            String billNo = IXqcConst.createBillNo(BillType.CJRK);
            //根据生产任务号查询车间
            Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(k));
            String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
            VtuzxMap map = (VtuzxMap) v;
            double count = VtuzxUtil.getDouble(map, "count");
            int boxCount = VtuzxUtil.getInt(map, "boxCount");
            Document prdInDoc = new Document("billNo", billNo)
                    .append("stockNo", stockNo)
                    .append("boxCount", boxCount)
                    .append("produceHouseName", produceHouseName)
                    .append("count", count)
                    .append("status", BillStatus.Save.toString());
            if (finalReturnType) {
                prdInDoc.append("return", true);
                prdInDoc.append("taskBillNo", k);
            }
            if (finalDesaltingType) {
                prdInDoc.append("desalting", true);
                prdInDoc.append("taskBillNo", k);
            }
            prdInDao.insertBill(_userId, userName, prdInDoc);
            try {
                Document detailUpdateVal = new Document("$set", new Document("billNo", billNo));
                detailUpdateVal.append("$unset", new Document("isTemp", 1));
                prdInDetailDao.updateManyRedirect(opCond, detailUpdateVal);
                prdInDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
                auditPrdInOrder(_userId, userName, stockNo, billNo);//审核退料单
            } catch (Exception e) {
                Criteria rollbackCond = Criteria.where("billNo").is(billNo);
                prdInDao.deleteOne(rollbackCond);
                prdInDetailDao.updateManyRedirect(rollbackCond,
                        new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
                prdInDetailBoxDao.updateManyRedirect(rollbackCond,
                        new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
                try {
                    throw e;
                } catch (VtuzxException vtuzxException) {
                    vtuzxException.printStackTrace();
                }
            }
//            //传金蝶退料单
//            try {
//                syncKingdeeOrderService.syncReturn(_userId,userName,billNo,"pda");
//            } catch (Exception e){
//                _logger.info(e.getMessage());
//            }
        });

    }

    /**
     * 生产入库单审批
     *
     * @param _userId  用户ID
     * @param userName 用户名
     * @param stockNo  仓库编码
     * @param billNo   单据号
     * @throws VtuzxException 异常处理
     */
    public void auditPrdInOrder(ObjectId _userId, String userName, String stockNo, String billNo) throws VtuzxException {
        Criteria getCond = Criteria.where("billNo").is(billNo);
        Document prdInDoc = prdInDao.findOne(getCond);
        boolean desalting = VtuzxUtil.getBoolean(prdInDoc, "desalting");
        boolean returning = VtuzxUtil.getBoolean(prdInDoc, "return");
        String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(getCond, null, 0, 0);
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(getCond, null, 0, 0);
        List<Document> prdInDetailBoxList = new ArrayList<>();
        List<String> colBoxNoList = new ArrayList<>();
        while (prdInDetailBoxItr.hasNext()) {
            Document box = prdInDetailBoxItr.next();
            prdInDetailBoxList.add(box);
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            colBoxNoList.add(boxNo);
        }

        VtuzxMap updateColBillMap = new VtuzxMap();
        Iterator<Document> purColDetailItr = prdColDetailDao.findList(Criteria.where("boxNo").in(colBoxNoList), null, 0, 0);
        while (purColDetailItr.hasNext()) {
            Document purColDetailDoc = purColDetailItr.next();
            double count = VtuzxUtil.getDouble(purColDetailDoc, "count");
            String colBillNo = VtuzxUtil.getString(purColDetailDoc, "billNo");
            VtuzxMap updateColBill = VtuzxUtil.getObject(updateColBillMap, colBillNo);
            if (VtuzxUtil.isEmpty(updateColBill)) {
                VtuzxMap smallColBillMap = new VtuzxMap();
                smallColBillMap.append("count", count).append("boxCount", 1);
                updateColBillMap.append(colBillNo, smallColBillMap);
            } else {
                double sCount = VtuzxUtil.getDouble(updateColBill, "count");
                int sBoxCount = VtuzxUtil.getInt(updateColBill, "boxCount");
                updateColBillMap.append(colBillNo, new VtuzxMap("count", sCount + count).append("boxCount", sBoxCount + 1));
            }
        }
        List<BillMaterial> prdInDetailList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        while (prdInDetailItr.hasNext()) {
            Document prdInDetail = prdInDetailItr.next();
            BillMaterial billMaterial = new BillMaterial();
            ObjectId _prdInDetailId = prdInDetail.getObjectId(IVtuzxConst.Key__id);
            billMaterial.setMaterialNo(VtuzxUtil.getString(prdInDetail, "materialNo"));
            billMaterial.setUnit(VtuzxUtil.getString(prdInDetail, "unit"));
            billMaterial.setBatchNo(VtuzxUtil.getString(prdInDetail, "batchNo"));
            billMaterial.setProduceDate(VtuzxUtil.getString(prdInDetail, "produceDate"));
            billMaterial.setExp(VtuzxUtil.getInt(prdInDetail, "exp"));
            List<BillMaterialBox> boxList = new ArrayList<>();
            for (Document boxDoc : prdInDetailBoxList) {
                ObjectId _detailId = VtuzxUtil.getObject(boxDoc, "_detailId");
                String barcodeType = VtuzxUtil.getString(boxDoc, "barcodeType");
                if (_prdInDetailId.equals(_detailId)) {
                    BillMaterialBox box = new BillMaterialBox();
                    String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
                    box.setBoxNo(boxNo);
                    box.setRfid(VtuzxUtil.getString(boxDoc, "rfid"));
                    box.setCount(VtuzxUtil.getDouble(boxDoc, "count"));
                    box.setLocationNo(VtuzxUtil.getString(prdInDetail, "locationNo"));
                    box.setTraceBack(VtuzxUtil.getObject(boxDoc, "traceBack"));
                    boxList.add(box);
                    if (!"BC".equals(barcodeType)) {
                        boxNoList.add(boxNo);
                    }
                }
                billMaterial.setBoxList(boxList);
            }
            prdInDetailList.add(billMaterial);
        }
        prdInDao.audit(_userId, userName, billNo);
        // 更新收货单入库状态
        if (!VtuzxUtil.isEmpty(boxNoList)) {
            try {
                UpdateResult updRes = prdColDetailDao.updateMany(Criteria.where("boxNo").in(boxNoList).and("inStock").ne(true),
                        new Document("perInBillNo", billNo).append("perInTime", new Date()).append("inStock", true));
                if (updRes.getModifiedCount() != boxNoList.size()) {
                    throw new VtuzxException(IXqcConst.Msg_E_XQC_stock_pur_col_in_stock);
                }
            } catch (Exception e) {
                prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
                prdInDao.unaudit(billNo);
                throw e;
            }
        }
        // 更新即时库存
        try {
            inventoryService.addInventory(_userId, userName, BillEvent.Audit, BillType.CGRK, stockNo, billNo, prdInDetailList);
        } catch (Exception e) {
            prdInDao.unaudit(billNo);
            if (!VtuzxUtil.isEmpty(boxNoList)) {
                prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
            }
            throw e;
        }
        //变品传金蝶
//        if (desalting) {
//            try {
//                syncKingdeeOrderService.syncDesaltingInStock(_userId, userName, taskBillNo, billNo, "pda");
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
//        }
//        //退料传金蝶
//        if (returning) {
//            try {
//                syncKingdeeOrderService.syncReturn(_userId, userName, billNo, "pda");
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
//        }

        //做收货单的已入库数量重量的反写
        updateColBillMap.forEach((k, v) -> {
            VtuzxMap map = (VtuzxMap) v;
            double sCount = VtuzxUtil.getDouble(map, "count");
            int sBoxCount = VtuzxUtil.getInt(map, "boxCount");
            prdColDao.updateOneRedirect(Criteria.where("billNo").is(k), new Document("$inc", new Document("inStockCount", sCount).append("inStockBoxCount", sBoxCount)));
        });

    }

    /**
     * 采购入库单审批
     *
     * @param _userId  用户ID
     * @param userName 用户名
     * @param stockNo  仓库编码
     * @param billNo   单据号
     * @throws VtuzxException 异常处理
     */
    public void unauditPrdInOrder(ObjectId _userId, String userName, String stockNo, String billNo) throws VtuzxException {
//        Criteria getCond = Criteria.where("billNo").is(billNo);
//        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(getCond, null, 0, 0);
//        List<String> boxNoList = new ArrayList<>();
//        while(prdInDetailBoxItr.hasNext()) {
//            boxNoList.add(VtuzxUtil.getString(prdInDetailBoxItr.next(), "boxNo"));
//        }
//        prdInDao.unaudit(billNo);
//        // 取消收货单入库状态
//        try {
//            prdInDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList).and("perInBillNo").is(billNo),
//                    new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
//        } catch(Exception e) {
//            prdInDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", BillStatus.Audit.toString()));
//            throw e;
//        }
//        // 更新即时库存
//        try {
//            inventoryService.reduceInventory(_userId, userName, BillEvent.Unaudit, BillType.CGRK, stockNo, billNo, boxNoList);
//        } catch(Exception e) {
//            prdInDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", BillStatus.Audit.toString()));
//            prdInDetailDao.updateMany(Criteria.where("boxNo").in(boxNoList),
//                    new Document("perInBillNo", billNo).append("perInTime", new Date()).append("inStock", true));
//            throw e;
//        }
    }

    @Override
    public VtuzxMap addUserPrdInMaterialBoxList(ObjectId _userId, String userName, String stockNo, String locationNo, List<Map<String, Object>> boxList) throws VtuzxException {
        //判断类型，只允许退料和变品退料的
        for (Map<String, Object> box : boxList) {
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            double count = VtuzxUtil.getDouble(box, "count");
            String colType = VtuzxUtil.getString(box, "colType");
            if ("return".equals(colType) || "desaltingIn".equals(colType)) {
                try {
                    VtuzxMap prdColDetail = getPrdColMaterial(boxNo);
                    addUserPrdInMaterialBoxInner(prdColDetail, _userId, userName, stockNo, locationNo, boxNo, count, false, "");
                } catch (Exception e) {
                    throw new VtuzxException(e.getMessage());
//                _logger.info("addUserprdInMaterialBoxList error:" + e.getMessage());
                }
            } else {
                throw new VtuzxException("该箱不是退料");
            }

        }
        return getUserPrdInMaterial(_userId, stockNo);
    }

    @Override
    public VtuzxMap addUserPrdInMaterialBox(ObjectId _userId, String userName, String stockNo, String locationNo, String boxNo, double count) throws VtuzxException {
        VtuzxMap prdColDetail = getPrdColMaterial(boxNo);
        ObjectId _detailId = addUserPrdInMaterialBoxInner(prdColDetail, _userId, userName, stockNo, locationNo, boxNo, count, false, "");
        Document prdInDetailDoc = prdInDetailDao.findById(_detailId);
        return new VtuzxMap("boxCount", VtuzxUtil.getObject(prdInDetailDoc, "boxCount"))
                .append("count", VtuzxUtil.getObject(prdInDetailDoc, "count"))
                .append("colBoxCount", VtuzxUtil.getObject(prdColDetail, "boxCount"))
                .append("colCount", VtuzxUtil.getObject(prdColDetail, "count"));
    }

    /**
     * 车间入库增加临时箱号内部方法
     *
     * @param prdColDetail 收货单详细
     * @param _userId      用户ID
     * @param userName     用户名
     * @param stockNo      仓库编码
     * @param locationNo   仓位编码
     * @param boxNo        箱号
     * @param count        数量
     * @return 信息ID
     * @throws VtuzxException 异常处理
     */
    public ObjectId addUserPrdInMaterialBoxInner(VtuzxMap prdColDetail, ObjectId _userId, String userName, String stockNo, String locationNo, String boxNo, double count, boolean task, String taskBillNo) throws VtuzxException {
        String barcodeType = VtuzxUtil.getString(prdColDetail, "barcodeType");
        String colType = VtuzxUtil.getString(prdColDetail, "colType");
        if ("BC".equals(barcodeType)) {
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo + "|;batch";
        }

        Iterator<Document> boxItr = prdInDetailBoxDao.findList(Criteria.where("_createUserId").is(_userId).and("isTemp").is(true), null, 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            String innerColType = VtuzxUtil.getString(boxDoc, "colType");
            if (!innerColType.equals(colType)) {
                throw new VtuzxException("请勿同时添加不同收货类型的箱子");
            }

        }

        if (!"return".equals(colType)) {
            Document scanBoxDoc = prdInDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
            if (scanBoxDoc != null) {
                throw new VtuzxException("箱号已入库!");
            }
        } else {
            Document scanBoxDoc = prdInDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo).and("isTemp").is(true));
            if (scanBoxDoc != null) {
                throw new VtuzxException("箱号已入库!");
            }
        }

        String billNo = VtuzxUtil.getString(prdColDetail, "billNo");
        String taskBillNumber = VtuzxUtil.getString(prdColDetail, "taskBillNo");
        String materialNo = VtuzxUtil.getString(prdColDetail, "materialNo");
        String materialName = VtuzxUtil.getString(prdColDetail, "materialName");
        String materialSpec = VtuzxUtil.getString(prdColDetail, "materialSpec");
        String batchNo = VtuzxUtil.getString(prdColDetail, "batchNo");
        String rfid = VtuzxUtil.getString(prdColDetail, "rfid");
        String produceDate = VtuzxUtil.getString(prdColDetail, "produceDate");
        int exp = VtuzxUtil.getInt(prdColDetail, "exp");
        String unit = VtuzxUtil.getString(prdColDetail, "unit");
        List<String> traceBack = VtuzxUtil.getObject(prdColDetail, "traceBack");
        int colBoxCount = VtuzxUtil.getInt(prdColDetail, "boxCount");
        double colCount = VtuzxUtil.getDouble(prdColDetail, "countTotal");
        Criteria detailCond = Criteria.where("_createUserId").is(_userId);
        detailCond.and("isTemp").is(true);
        detailCond.and("billNo").is(billNo);
        detailCond.and("stockNo").is(stockNo);
        detailCond.and("locationNo").is(locationNo);
        detailCond.and("materialNo").is(materialNo);
        detailCond.and("batchNo").is(batchNo);
        detailCond.and("produceDate").is(produceDate);
        detailCond.and("exp").is(exp);
        detailCond.and("unit").is(unit);
        Document detail = prdInDetailDao.findOne(detailCond);
        Document updateVal = new Document();
        double nowColCount = 0.0;
        int nowColBoxCount = 0;
        List<VtuzxMap> traceBackList = new ArrayList<>();
        if (traceBack != null) {
            for (String traceNo : traceBack) {
                VtuzxMap traceMap = new VtuzxMap("traceBackNo", traceNo).append("status", "in");
                traceBackList.add(traceMap);
            }
        }
        if ("BC".equals(barcodeType)) {
            nowColCount = count;
            nowColBoxCount = 1;
//            nowColCount = VtuzxUtil.getDouble(prdColDetail, "count");
//            nowColBoxCount = VtuzxUtil.getInt(prdColDetail, "boxCount");
//            if (detail != null) {
//                nowColCount += VtuzxUtil.getDouble(detail, "count");
//                nowColBoxCount += VtuzxUtil.getInt(detail, "boxCount");
//            }
        } else {
            Iterator<Document> otherColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("createTime", -1), 0, 0);
            while (otherColDetailItr.hasNext()) {
                Document otherColDetailDoc = otherColDetailItr.next();
                boolean inStock = VtuzxUtil.getBoolean(otherColDetailDoc, "inStock");
                double otherColCount = VtuzxUtil.getDouble(otherColDetailDoc, "count");
                if (!inStock) {
                    nowColCount += otherColCount;
                    nowColBoxCount++;
                }
            }
        }

        if (detail == null) {
            updateVal.append("isTemp", true);
            updateVal.append("billNo", billNo);
            updateVal.append("stockNo", stockNo);
            updateVal.append("locationNo", locationNo);
            updateVal.append("materialNo", materialNo);
            updateVal.append("materialName", materialName);
            updateVal.append("materialSpec", materialSpec);
            updateVal.append("unit", unit);
            updateVal.append("batchNo", batchNo);
            updateVal.append("produceDate", produceDate);
            updateVal.append("exp", exp);
            updateVal.append("_createUserId", _userId);
            updateVal.append("createUserName", userName);
            updateVal.append("boxCount", 1);
            updateVal.append("count", count);
            updateVal.append("colCount", colCount);
            updateVal.append("colBoxCount", colBoxCount);
            updateVal.append("nowColCount", nowColCount);
            updateVal.append("nowColBoxCount", nowColBoxCount);
            if (task) {
                updateVal.append("task", true);
                updateVal.append("taskBillNo", taskBillNumber);
            } else if ("return".equals(colType)) {
                updateVal.append("return", true);
                updateVal.append("taskBillNo", taskBillNumber);
            } else if ("desaltingIn".equals(colType)) {
                updateVal.append("desalting", true);
                updateVal.append("taskBillNo", taskBillNumber);
            }

        } else {
            updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count)).append("$set", new Document("nowColCount", nowColCount).append("nowColBoxCount", nowColBoxCount));
        }
        ObjectId _detailId;
        if (detail == null) {
            _detailId = prdInDetailDao.insertOne(updateVal);
        } else {
            _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
            prdInDetailDao.updateByIdRedirect(_detailId, updateVal);
        }
        Document detailBox = new Document();
        detailBox.append("isTemp", true);
        detailBox.append("_detailId", _detailId);
        detailBox.append("boxNo", boxNo);
        detailBox.append("rfid", rfid);
        detailBox.append("count", count);
        detailBox.append("unit", unit);
        detailBox.append("_createUserId", _userId);
        detailBox.append("createUserName", userName);
        detailBox.append("stockNo", stockNo);
        detailBox.append("barcodeType", barcodeType);
        detailBox.append("traceBack", traceBackList);
        detailBox.append("colType", colType);
        if (task) {
            detailBox.append("task", true);
            detailBox.append("taskBillNo", taskBillNumber);
        } else if ("return".equals(colType)) {
            detailBox.append("return", true);
            detailBox.append("taskBillNo", taskBillNumber);
        } else if ("desaltingIn".equals(colType)) {
            detailBox.append("desalting", true);
            detailBox.append("taskBillNo", taskBillNumber);
        }
        prdInDetailBoxDao.insertOne(detailBox);
        return _detailId;
    }

    @Override
    public VtuzxMap deleteUserPrdInMaterialBox(ObjectId _userId, String id) {
        Document prdInDetailBoxDoc = prdInDetailBoxDao.findOne(Criteria.where("_detailId").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(prdInDetailBoxDoc, "_detailId");
        prdInDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (prdInDetailBoxItr.hasNext()) {
            Document doc = prdInDetailBoxItr.next();
            double prdInDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = prdInDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0) {
            prdInDetailDao.deleteById(_detailId);
        } else {
            prdInDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public void deleteUserPrdInMaterial(ObjectId _userId, String id) {
        prdInDetailDao.deleteById(FastUtil.convertId(id));
        prdInDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserPrdIn(ObjectId _userId, String stockNo) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        prdInDetailDao.deleteMany(cond);
        prdInDetailBoxDao.deleteMany(cond);
    }

    @Override
    public VtuzxMap updateUserPrdInMaterialBox(ObjectId _userId, String boxNo, double count) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("boxNo").is(boxNo).and("isTemp").is(true);
        Document detailBoxDoc = prdInDetailBoxDao.findOne(cond);
        String stockNo = VtuzxUtil.getString(detailBoxDoc, "stockNo");
        ObjectId _detailId = VtuzxUtil.getObject(detailBoxDoc, "_detailId");
        prdInDetailBoxDao.updateOne(cond, new Document("count", count));
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true), new Document("stockNo", 1), 0, 0);
        int boxCount = 0;
        double total = 0;
        while (prdInDetailBoxItr.hasNext()) {
            Document doc = prdInDetailBoxItr.next();
            double prdInDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = prdInDetailBoxCount + total;
            boxCount++;
        }
        prdInDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public VtuzxMap getUserPrdInMaterial(ObjectId _userId, String stockNo) {
        List<VtuzxMap> prdInDetailList = new ArrayList<>();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            VtuzxMap prdInDetailMap = new VtuzxMap(prdInDetailDoc);
            prdInDetailMap.remove(IVtuzxConst.Key_createTime);
            prdInDetailMap.remove(IVtuzxConst.Key_updateTime);
            prdInDetailMap.remove("_createUserId");
            prdInDetailMap.remove("createUserName");
            prdInDetailMap.remove("_updateUserId");
            prdInDetailMap.remove("updateUserName");
            prdInDetailMap.append("id", VtuzxUtil.removeString(prdInDetailMap, IVtuzxConst.Key__id));
            prdInDetailList.add(prdInDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, prdInDetailList);
    }

    @Override
    public VtuzxMap getUserPrdInMaterialBox(ObjectId _userId, String detailId) {
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(
                Criteria.where("_createUserId").is(_userId).and("_detailId").is(FastUtil.convertId(detailId)).and("isTemp").is(true), null, 0, 0);
        List<VtuzxMap> dataList = new ArrayList<>();
        while (prdInDetailBoxItr.hasNext()) {
            Document boxDoc = prdInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(boxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdInBill(ObjectId _userId, int pageIndex, int pageSize, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        List<VtuzxMap> dataList = new ArrayList<>();
        Criteria cond = new Criteria("task").ne(true).and("desalting").ne(true).and("return").ne(true);
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo) || !VtuzxUtil.isEmpty(boxNo)) {
            List<String> inBillNoList = new ArrayList<>();
            if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) {
                Criteria smallCond = new Criteria();
                if (!VtuzxUtil.isEmpty(materialNo)) {
                    smallCond.and("materialNo").is(materialNo);
                }
                if (!VtuzxUtil.isEmpty(batchNo)) {
                    smallCond.and("batchNo").is(batchNo);
                }
                Iterator<Document> purInDetailItr = prdInDetailDao.findList(smallCond, null, 0, 0);
                while (purInDetailItr.hasNext()) {
                    Document purInDetailDoc = purInDetailItr.next();
                    String purInBillNo = VtuzxUtil.getString(purInDetailDoc, "billNo");
                    inBillNoList.add(purInBillNo);
                }
            } else {
                Iterator<Document> boxItr = prdInDetailBoxDao.findList(Criteria.where("boxNo").is(boxNo), null, 0, 0);
                while (boxItr.hasNext()) {
                    Document boxDoc = boxItr.next();
                    inBillNoList.add(VtuzxUtil.getString(boxDoc, "billNo"));
                }
            }

            Iterator<Document> purInItr = prdInDao.findList(Criteria.where("billNo").in(inBillNoList), null, 0, 0);
            while (purInItr.hasNext()) {
                Document purInDoc = purInItr.next();
                VtuzxMap purInMap = new VtuzxMap(purInDoc);
                purInMap.append("id", VtuzxUtil.removeString(purInMap, IVtuzxConst.Key__id));
                purInMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInMap, "createTime")));
                dataList.add(purInMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_data, dataList);
        }

        VtuzxPage page = prdInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdInBillDetail(ObjectId _userId, String stockNo, String billNo) {
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo));
        String createUserName = VtuzxUtil.getString(prdInDoc, "createUserName");
        int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");
        double count = VtuzxUtil.getDouble(prdInDoc, "count");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdInDoc, "createTime"));
        VtuzxMap header = new VtuzxMap("billNo", billNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("stockNo", stockNo)
                .append("boxCount", boxCount)
                .append("count", count);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            VtuzxMap prdInDetailMap = new VtuzxMap(prdInDetailDoc);
            prdInDetailMap.remove(IVtuzxConst.Key_createTime);
            prdInDetailMap.remove(IVtuzxConst.Key_updateTime);
            prdInDetailMap.remove("_createUserId");
            prdInDetailMap.remove("createUserName");
            prdInDetailMap.remove("_updateUserId");
            prdInDetailMap.remove("updateUserName");
            prdInDetailMap.append("id", VtuzxUtil.removeString(prdInDetailMap, IVtuzxConst.Key__id));
            dataList.add(prdInDetailMap);
        }
        for (VtuzxMap data : dataList) {
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            data.append("unit", fBaseUnitIdFName);

        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdInBillDetailBox(ObjectId _userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(cond, null, 0, 0);
        while (prdInDetailBoxItr.hasNext()) {
            Document boxDoc = prdInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(boxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            Document detailDoc = prdInDetailDao.findById(FastUtil.convertId(detailId));
            String materialNo = VtuzxUtil.getString(detailDoc, "materialNo");
            boxMap.append("materialNo", materialNo);
            dataList.add(boxMap);
        }
        for (VtuzxMap data : dataList) {
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            data.append("unit", fBaseUnitIdFName);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    /**
     * 上传采购收货单
     */
    @Override
    public void uploadPrdColBill(ObjectId _userId, String userName, File file) throws Exception {
        List<VtuzxExcelSheet> sheets = VtuzxExcel.read(file);
        VtuzxExcelSheet sheet = sheets.get(0);
        int rowSize = sheet.rowSize();
        List<Map<String, Object>> newBillList = new ArrayList<>();
        String preMaterialNo = "";
        String preBatchNo = "";
        Map<String, Object> bill = null;
        for (int i = 1; i < rowSize; i++) {
            String materialNo = "";
            String materialName = "";
            String materialSpec = "";
            String batchNo = "";
            double prdCount = 0;
            String boxNo = "";
            double count = 0;
            String comment = "";
            int cellSize = sheet.row(i).cellSize();
            for (int ci = 0; ci < cellSize; ci++) {
                if (sheet.row(i).cell(ci).col() == 0) materialNo = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 1) materialName = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 2) materialSpec = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 3) batchNo = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 4) prdCount = sheet.row(i).cell(ci).doubleCellValue();
                if (sheet.row(i).cell(ci).col() == 5) boxNo = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 6) count = sheet.row(i).cell(ci).doubleCellValue();
                if (sheet.row(i).cell(ci).col() == 7) comment = sheet.row(i).cell(ci).strCellValue();
            }

            if (!materialNo.equals(preMaterialNo) || !batchNo.equals(preBatchNo)) {
                bill = new HashMap<>();
                newBillList.add(bill);
                bill.put("materialNo", materialNo);
                bill.put("materialName", materialName);
                bill.put("materialSpec", materialSpec);
//                bill.put("supplierNo", "");
//                bill.put("supplierName", "");
                bill.put("batchNo", batchNo);
                bill.put("prdCount", prdCount);
//                bill.put("produceDate", "");
//                bill.put("exp", "");
                List<Map<String, Object>> boxList = new ArrayList<>();
                bill.put("boxList", boxList);
            }
            List<Map<String, Object>> boxList = VtuzxUtil.getObject(bill, "boxList");
            boxList.add(new VtuzxMap("boxNo", boxNo).append("count", count).append("comment", comment));
            preMaterialNo = materialNo;
            preBatchNo = batchNo;
        }
        for (Map<String, Object> newBill : newBillList) {
            VtuzxMap res = savePrdColBill(_userId, userName, newBill);
            String billNo = VtuzxUtil.getString(res, "billNo");
            auditPrdColBill(_userId, userName, billNo);
        }
    }

    @Override
    public VtuzxMap savePrdColBill(ObjectId _userId, String userName, Map<String, Object> param) throws VtuzxException {
        // 获取用户信息
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document prdColDoc = prdColDao.findOne(Criteria.where("billNo").is(billNo));
        String colType = "";
        if (!VtuzxUtil.isEmpty(prdColDoc)) {
            colType = VtuzxUtil.getString(prdColDoc, "colType");
        }
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        String unit = "";
        if (!VtuzxUtil.isEmpty(materialDoc)) {
            unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        } else {
            unit = "kg";
        }
        //判断正常任务不允许做任务以外的品
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(prdTaskDoc, "type");//任务类型
        if ("product".equals(type)) {
            Document taskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
            String taskMaterialNo = VtuzxUtil.getString(taskDetailDoc, "materialNo");//任务的物料
            if (!taskMaterialNo.equals(materialNo)) {
                throw new VtuzxException("不允许生产任务以外的物料");
            }
        }
        Document doc = new Document();
        doc.append("materialNo", materialNo);
        doc.append("materialName", VtuzxUtil.getString(param, "materialName"));
        doc.append("materialSpec", VtuzxUtil.getString(param, "materialSpec"));
        doc.append("supplierBatchNo", VtuzxUtil.getString(param, "supplierBatchNo"));
        doc.append("batchNo", VtuzxUtil.getString(param, "batchNo"));
        doc.append("produceDate", VtuzxUtil.getString(param, "produceDate"));
        doc.append("exp", VtuzxUtil.getInt(param, "exp"));
        doc.append("prdCount", VtuzxUtil.getDouble(param, "prdCount"));
        doc.append("remark", VtuzxUtil.getString(param, "remark"));
        doc.append("taskBillNo", VtuzxUtil.getString(param, "taskBillNo"));
        doc.append("isPrint", "unseal");
        if (VtuzxUtil.isEmpty(colType)) {
            doc.append("colType", "prdCol");
        } else {
            doc.append("colType", colType);
        }
        // 计算总箱数和总称重
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        double total = 0;
        for (Map<String, Object> box : boxList) {
            double count = VtuzxUtil.getDouble(box, "count");
            total += count;
        }
        doc.append("count", total);
        doc.append("unit", unit);
        doc.append("boxCount", boxList.size());

        List<Document> detailList = new ArrayList<>();
        if (VtuzxUtil.isEmpty(billNo)) {
            billNo = IXqcConst.createBillNo(BillType.CJSH);
            _logger.info(String.format("新建单据号：%s", billNo));
            doc.append("billNo", billNo);
            doc.append("status", BillStatus.Save.toString());
            doc.append("_createUserId", _userId);
            doc.append("createUserName", userName);
            prdColDao.insertOne(doc);
        } else {
            doc.append("_updateUserId", _userId);
            doc.append("updateUserName", userName);
            UpdateResult res = prdColDao.updateOne(Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString()), doc);
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
            Iterator<Document> detailItr = prdColDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (detailItr.hasNext()) {
                detailList.add(detailItr.next());
            }
        }
        List<ObjectId> _delIds = new ArrayList<>();
        List<Document> insertList = new ArrayList<>();
        for (Map<String, Object> box : boxList) {
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            String comment = VtuzxUtil.getString(box, "comment");
            boolean exist = false;
            for (Document detail : detailList) {
                String boxNoDB = VtuzxUtil.getString(detail, "boxNo");
                if (boxNo.equals(boxNoDB)) {
                    prdColDetailDao.updateById(
                            detail.getObjectId(IVtuzxConst.Key__id),
                            new Document("count", VtuzxUtil.getDouble(box, "count"))
                                    .append("_updateUserId", _userId)
                                    .append("updateUserName", userName)
                                    .append("comment", comment)
                    );
                    exist = true;
                    detailList.remove(detail);
                    break;
                }
            }
            if (!exist) {
                insertList.add(new Document("count", VtuzxUtil.getDouble(box, "count"))
                        .append("unit", unit)
                        .append("billNo", billNo)
                        .append("colType", "prdCol")
                        .append("boxNo", VtuzxUtil.getString(box, "boxNo"))
                        .append("comment", VtuzxUtil.getString(box, "comment"))
                        .append("inStock", false)
                        .append("_insertUserId", _userId)
                        .append("insertUserName", userName));
            }
        }
        for (Document detail : detailList) {
            _delIds.add(VtuzxUtil.getObject(detail, IVtuzxConst.Key__id));
        }
        _logger.info(String.format("删除单据分录行：%d", _delIds.size()));
        if (_delIds.size() > 0) {
            prdColDetailDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(_delIds));
        }
        _logger.info(String.format("新建单据分录行：%d", insertList.size()));
        if (insertList.size() > 0) {
            prdColDetailDao.insertMany(insertList);
        }
        return new VtuzxMap("billNo", billNo);
    }


    @Override
    public void savePrdColBillSupplier(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String supplierBatchNo = VtuzxUtil.getString(param, "supplierBatchNo");
        prdColDao.updateOne(Criteria.where("billNo").is(billNo), new Document("supplierBatchNo", supplierBatchNo));
    }

    @Override
    public void saveSimpleColBill(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        List<VtuzxMap> boxList = VtuzxUtil.getObject(param, "boxList");
        for (Map<String, Object> box : boxList) {
            String billNo = VtuzxUtil.getString(box, "billNo");
            String taskBillNo = VtuzxUtil.getString(box, "taskBillNo");
            String comment = VtuzxUtil.getString(box, "comment");
            String batchNo = VtuzxUtil.getString(box, "batchNo");
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            double count = VtuzxUtil.getDouble(box, "count");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            if (VtuzxUtil.isEmpty(materialDoc)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String materialName = VtuzxUtil.getString(materialDoc, "fName");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            String materialSpec = VtuzxUtil.getString(materialDoc, "fSpecification");
            Document colDoc = new Document("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialSpec", materialSpec)
                    .append("materialName", materialName)
                    .append("batchNo", batchNo)
                    .append("colType", "prdCol")
                    .append("remark", comment)
                    .append("count", count)
                    .append("prdCount", count)
                    .append("unit", unit)
                    .append("boxCount", 1)
                    .append("billNo", billNo)
                    .append("taskBillNo", taskBillNo)
                    .append("status", BillStatus.Audit.toString())
                    .append("_createUserId", userId)
                    .append("createUserName", name)
                    .append("_auditUserId", userId)
                    .append("auditUserName", name)
                    .append("isPrint", "unseal")
                    .append("auditTime", new Date());
            prdColDao.insertOne(colDoc);

            Document colDetailDoc = new Document("count", count)
                    .append("unit", unit)
                    .append("billNo", billNo)
                    .append("boxNo", boxNo)
                    .append("comment", comment)
                    .append("inStock", false)
                    .append("_insertUserId", userId)
                    .append("insertUserName", name);
            prdColDetailDao.insertOne(colDetailDoc);
        }
    }

    @Override
    public void deletePrdColBill(ObjectId _userId, String userName, String billNo) throws VtuzxException {
        _logger.info(String.format("删除人员，userName:%s,userId:%s,单据编号:%s", userName, _userId, billNo));
        DeleteResult res = prdColDao.deleteOne(Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString()));
        if (res.getDeletedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        prdColDetailDao.deleteMany(Criteria.where("billNo").is(billNo));
    }

    @Override
    public VtuzxMap auditPrdColBill(ObjectId _userId, String userName, String billNo) throws VtuzxException {
        Criteria cond = Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString());
        Document updateDoc = new Document("status", BillStatus.Audit.toString());
        updateDoc.append("_auditUserId", _userId);
        updateDoc.append("auditUserName", userName);
        updateDoc.append("auditTime", new Date());
        UpdateResult res = prdColDao.updateOne(cond, updateDoc);
        if (res.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return new VtuzxMap("status", BillStatus.Audit.toString());
    }

    @Override
    public VtuzxMap unauditPrdColBill(ObjectId _userId, String name, String billNo) throws VtuzxException {
        _logger.info(String.format("反审人员，userName:%s", name));
        Iterator<Document> prdColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdColDetailItr.hasNext()) {
            Document prdColDetailDoc = prdColDetailItr.next();
            boolean inStock = VtuzxUtil.getBoolean(prdColDetailDoc, "inStock");
            if (inStock) {
                throw new VtuzxException("订单存在已入库的分录,不能进行反审操作");
            }
        }
        Criteria cond = Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Audit.toString());
        Document updateDoc = new Document("$set", new Document("status", BillStatus.Save.toString()).append("unAuditName", name));
        updateDoc.append("$unset", new Document("_auditUserId", 1).append("auditUserName", 1).append("auditTime", 1));
        UpdateResult res = prdColDao.updateOneRedirect(cond, updateDoc);
        if (res.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return new VtuzxMap("status", BillStatus.Save.toString());
    }

    @Override
    public VtuzxMap getPrdColMaterial(String boxNoKey) throws VtuzxException {
        String boxNo;
        boolean isTraceBack = false;
        if (boxNoKey.contains("|;")) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 5) {
                String supplierNo = boxValues[0];
                String materialNo = boxValues[1];
                String batchNo = boxValues[2];
                String flowNo = boxValues[3];
                int count = Integer.parseInt(boxValues[4]);
                return getPrdColMaterial(boxNoKey, supplierNo, materialNo, batchNo, flowNo, count);
            }
            boxNo = boxValues[boxValues.length - 1];
        } else if (boxNoKey.startsWith("http")) {
            isTraceBack = true;
            boxNo = boxNoKey;
        } else {
            boxNo = boxNoKey;
        }
        Document box = null;
        if (isTraceBack) {
            box = prdColDetailDao.findOne(Criteria.where("traceBack").in(boxNo).and("inStock").is(false));
        } else {
            box = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo).and("inStock").is(false));
        }
        if (box == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
//        boolean inStock = VtuzxUtil.getBoolean(box, "inStock");
//        if (inStock) {
//            throw new VtuzxException(IXqcConst.Msg_E_XQC_in_stock, boxNo);
//        }
        String billNo = VtuzxUtil.getString(box, "billNo");
        Document bill = prdColDao.findOne(Criteria.where("billNo").is(billNo));
        if (bill == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
        if (!BillStatus.Audit.hit(VtuzxUtil.getString(bill, "status"))) {
            throw new VtuzxException(String.format("箱号的采购收货单[%s]未审核!", billNo));
        }
        VtuzxMap res = new VtuzxMap(box);
        res.putAll(bill);
        res.remove(IVtuzxConst.Key__id);
        res.remove(IVtuzxConst.Key_createTime);
        res.remove(IVtuzxConst.Key_updateTime);
        res.remove("auditTime");
        res.remove("_createUserId");
        res.remove("_updateUserId");
        res.remove("createUserName");
        res.remove("updateUserName");
        res.remove("auditUserName");
        return res;
    }

    public VtuzxMap getPrdColMaterial(String boxNo, String supplierNo, String materialNo, String batchNo, String flowNo, int count) throws VtuzxException {
        VtuzxMap res = new VtuzxMap();
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        if (materialDoc == null) {
            throw new VtuzxException("物料不存在");
        }
        Document supplierDoc = supplierDao.findOne(Criteria.where("fNumber").is(supplierNo));
        if (supplierDoc == null) {
            throw new VtuzxException("供应商不存在");
        }
        res.append("materialNo", materialNo);
        res.append("materialName", VtuzxUtil.getString(materialDoc, "fName"));
        res.append("materialSpec", VtuzxUtil.getString(materialDoc, "fSpecification"));
        res.append("unit", VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber"));
        res.append("supplierNo", supplierNo);
        res.append("supplierName", VtuzxUtil.getString(supplierDoc, "fName"));
        res.append("batchNo", batchNo);
        res.append("count", count);
        res.append("boxCount", 1);
        res.append("billNo", "");
        res.append("boxNo", boxNo);
        res.append("inStock", false);
        res.append("rfid", "");
        res.append("barcodeType", "BC");
//        "supplierName": "",
//        "res": true,
//        "batchNo": "20220602134141",
//        "materialSpec": "混等",
//        "count": 5.0,
//        "supplierNo": "",
//        "materialName": "鲜海参 滚子",
//        "unit": "jin",
        return res;
    }

    @Override
    public VtuzxMap getPrdColMaterialByRfid(List<String> rfidList) {
        Iterator<Document> boxItr = prdColDetailDao.findList(Criteria.where("rfid").in(rfidList).and("inStock").ne(true), null, 0, 0);
        List<Document> boxList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        while (boxItr.hasNext()) {
            Document box = boxItr.next();
            String billNo = VtuzxUtil.getString(box, "billNo");
            boxList.add(box);
            if (!billNoList.contains(billNo)) {
                billNoList.add(billNo);
            }
        }
        if (VtuzxUtil.isEmpty(boxList)) {
            return new VtuzxMap(IVtuzxConst.Key_data, new ArrayList<>());
        }
        Iterator<Document> billItr = prdColDao.findList(Criteria.where("billNo").in(billNoList).and("status").is(BillStatus.Audit.toString()), null, 0, 0);
        VtuzxMap billMap = FastUtil.itr2Map(billItr, "billNo");
        for (int i = boxList.size() - 1; i >= 0; i--) {
            Document box = boxList.get(i);
            String billNo = VtuzxUtil.getString(box, "billNo");
            Document bill = VtuzxUtil.getObject(billMap, billNo);
            if (bill == null) {
                boxList.remove(i);
                continue;
            }
            if (bill.containsKey("count")) {
                bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
            }
            box.putAll(bill);
            box.remove(IVtuzxConst.Key__id);
            box.remove(IVtuzxConst.Key_createTime);
            box.remove(IVtuzxConst.Key_updateTime);
            box.remove("auditTime");
            box.remove("_createUserId");
            box.remove("_updateUserId");
            box.remove("createUserName");
            box.remove("updateUserName");
            box.remove("auditUserName");
        }
        return new VtuzxMap(IVtuzxConst.Key_data, boxList);
    }

    @Override
    public VtuzxMap getPrdColBill(ObjectId _userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String status = VtuzxUtil.getString(param, "status");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        boolean checkNoRfid = !VtuzxUtil.isEmpty(VtuzxUtil.getString(param, "isNoRfid"));
        boolean isNoRfid = VtuzxUtil.getBoolean(param, "isNoRfid");
        boolean isNoStockIn = VtuzxUtil.getBoolean(param, "isNoStockIn");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String materialName = VtuzxUtil.getString(param, "materialName");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String colType = VtuzxUtil.getString(param, "colType");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        List<String> auditTime = VtuzxUtil.getObject(param, "auditTime");
        List<String> produceDate = VtuzxUtil.getObject(param, "produceDate");
        String remark = VtuzxUtil.getString(param, "remark");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        Criteria cond = new Criteria();
//        if (checkNoRfid) {
//            cond.getCriteriaObject().append("$where", "this.boxCount " + (isNoRfid? "!=": "=") + " this.bindBoxCount");
//            cond.and("$where").is("this.boxCount " + (isNoRfid? "!=": "=") + " this.bindBoxCount");
//        }

        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        if (!VtuzxUtil.isEmpty(colType)) {
            cond.and("colType").is(colType);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(materialNo)) {
            cond.and("materialNo").regex(materialNo);
        }
        if (!VtuzxUtil.isEmpty(materialName)) {
            cond.and("materialName").regex("^.*" + materialName + ".*$");
        }
        if (!VtuzxUtil.isEmpty(batchNo)) {
            cond.and("batchNo").regex(batchNo);
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(auditTime)) {
            cond.and("auditTime").gte(VtuzxUtil.parseDate(auditTime.get(0))).lte(VtuzxUtil.parseDate(auditTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(produceDate)) {
            cond.and("produceDate").gte(produceDate.get(0)).lte(produceDate.get(1) + " 23:59:59");
        }
        if (!VtuzxUtil.isEmpty(VtuzxUtil.getString(param, "isNoStockIn"))) {
            Iterator<Document> colDetailItr = prdColDetailDao.findList(Criteria.where("inStock").ne(true), null, 0, 0);
            List<String> notInStockBillNoList = new ArrayList<>();
            while (colDetailItr.hasNext()) {
                Document colDetail = colDetailItr.next();
                String notInStockBillNo = VtuzxUtil.getString(colDetail, "billNo");
                if (!notInStockBillNoList.contains(notInStockBillNo)) {
                    notInStockBillNoList.add(notInStockBillNo);
                }
            }
            if (isNoStockIn) {
                cond.and("billNo").nin(notInStockBillNoList);
            } else {
                cond.and("billNo").in(notInStockBillNoList);
            }
        }
        if (!VtuzxUtil.isEmpty(remark)) {
            cond.and("remark").regex(remark);
        }
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").is(isPrint);
        }
//        VtuzxPage page = prdColDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        VtuzxPage page = prdColDao.getPageList(cond.getCriteriaObject(), checkNoRfid, isNoRfid, pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(itr -> {
            VtuzxMap data = new VtuzxMap(itr);
            int exp = VtuzxUtil.getInt(data, "exp");
            int boxCount = VtuzxUtil.getInt(data, "boxCount");
            int bindBoxCount = VtuzxUtil.getInt(data, "bindBoxCount");
            Date date = VtuzxUtil.parseDate(VtuzxUtil.getObject(data, "produceDate"));
            String expDate;
            if (exp <= 0) {
                expDate = "";
            } else {
                expDate = VtuzxUtil.formatYmdF(VtuzxUtil.calcDate(date, Calendar.DAY_OF_MONTH, exp));
            }
            data.append("isNotRfid", boxCount - bindBoxCount);

            data.append("expDate", expDate);
            data.append("id", VtuzxUtil.removeString(data, IVtuzxConst.Key__id));
            data.append(IVtuzxConst.Key_createTime, VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(data, IVtuzxConst.Key_createTime)));
            data.remove(IVtuzxConst.Key_updateTime);
            data.append("auditTime", VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(data, "auditTime")));
            data.remove("_createUserId");
            data.remove("_updateUserId");
            data.remove("_auditUserId");
            return data;
        });

        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdColBillDetail(ObjectId _userId, String billNo) throws VtuzxException {
        Document doc = prdColDao.findOne(Criteria.where("billNo").is(billNo));
        if (doc == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        VtuzxMap header = new VtuzxMap(doc);
//        header.append("billNo", VtuzxUtil.getObject(doc, "billNo"));
//        header.append("status", VtuzxUtil.getObject(doc, "status"));
//        header.append("materialNo", VtuzxUtil.getObject(doc, "materialNo"));
//        header.append("materialName", VtuzxUtil.getObject(doc, "materialName"));
//        header.append("materialSpec", VtuzxUtil.getObject(doc, "materialSpec"));
//        header.append("supplierNo", VtuzxUtil.getObject(doc, "supplierNo"));
//        header.append("supplierName", VtuzxUtil.getObject(doc, "supplierName"));
//        header.append("batchNo", VtuzxUtil.getObject(doc, "batchNo"));
//        header.append("produceDate", VtuzxUtil.getObject(doc, "produceDate"));
//        header.append("exp", VtuzxUtil.getObject(doc, "exp"));
//        header.append("prdCount", VtuzxUtil.getObject(doc, "prdCount"));
        String materialNo = VtuzxUtil.getString(header, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        if (materialDoc.isEmpty()) {
            throw new VtuzxException("物料不存在");
        }
        String unitName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
        header.append(IVtuzxConst.Key_createTime, VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(header, IVtuzxConst.Key_createTime)));
        Iterator<Document> boxItr = prdColDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("boxNo", 1), 0, 0);
        List<VtuzxMap> boxList = new ArrayList<>();
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            VtuzxMap prdColDetailMap = new VtuzxMap(boxDoc);
            prdColDetailMap.remove(IVtuzxConst.Key_createTime);
            prdColDetailMap.remove(IVtuzxConst.Key_updateTime);
            prdColDetailMap.remove("_createUserId");
            prdColDetailMap.remove("createUserName");
            prdColDetailMap.remove("_updateUserId");
            prdColDetailMap.remove("updateUserName");
            prdColDetailMap.append("id", VtuzxUtil.removeString(prdColDetailMap, IVtuzxConst.Key__id));
            prdColDetailMap.append("unitName", unitName);
            boxList.add(prdColDetailMap);
        }
        return new VtuzxMap("header", header).append("boxList", boxList);
    }

    @Override
    public VtuzxDownloadBean downloadPrdColBillBarcodeList(ObjectId _userId, List<String> billNoList) throws Exception {
        List<VtuzxMap> detailList = new ArrayList<>();
        for (String billNo : billNoList) {
            VtuzxMap detail = getPrdColBillDetail(_userId, billNo);
            detailList.add(detail);
        }
        return configService.downloadBillBarcode(BillType.CJSH, detailList);
    }


    @Override
    public VtuzxDownloadBean downloadPrdColBillBarcode(ObjectId _userId, String billNo) throws Exception {
        VtuzxMap detail = getPrdColBillDetail(_userId, billNo);
//        VtuzxMap header = VtuzxUtil.getObject(detail, "header");
//        List<VtuzxMap> boxList = VtuzxUtil.getObject(detail, "boxList");
        List<VtuzxMap> detailList = new ArrayList<>();
        detailList.add(detail);
        return configService.downloadBillBarcode(BillType.SCRK, detailList);
    }


    @Override
    public VtuzxMap taskBillToMaterialList(ObjectId userId, String userName, Map<String, Object> param) {
        Map<String, Object> dataMap = VtuzxUtil.getObject(param, "dataMap");
        String taskType = VtuzxUtil.getString(dataMap, "taskType");
        List<Map<String, Object>> dataList = VtuzxUtil.getObject(dataMap, "dataList");
        List<VtuzxMap> materialList = new ArrayList<>();
        if (taskType.equals("sorting")) {
            for (Map<String, Object> data : dataList) {
                double count = VtuzxUtil.getDouble(data, "count");
                VtuzxMap materialMap = new VtuzxMap();
                String materialNo = VtuzxUtil.getString(data, "materialNo");
                String materialName = VtuzxUtil.getString(data, "materialName");
                String materialModel = VtuzxUtil.getString(data, "materialModel");
                double numerator = VtuzxUtil.getDouble(data, "numerator");
                double denominator = VtuzxUtil.getDouble(data, "denominator");
                double scraprate = VtuzxUtil.getDouble(data, "scraprate");
                double childCount = count * (1 + scraprate);
                materialMap.append("childMaterialNo", materialNo)
                        .append("childMaterialName", materialName)
                        .append("childMaterialModel", materialModel)
                        .append("denominator", 1)
                        .append("numerator", 1)
                        .append("count", childCount)
                        .append("taskCount", count)
                        .append("pickCount", 0)
                        .append("notPickCount", childCount);
                materialList.add(materialMap);
            }
        } else {
            for (Map<String, Object> data : dataList) {
                String materialNo = VtuzxUtil.getString(data, "materialNo");
                String materialName = VtuzxUtil.getString(data, "materialName");
                String materialModel = VtuzxUtil.getString(data, "materialModel");
                double count = VtuzxUtil.getDouble(data, "count");


                List<Map<String, Object>> childList = VtuzxUtil.getObject(data, "childList");
                for (Map<String, Object> child : childList) {
                    VtuzxMap materialMap = new VtuzxMap();
                    materialMap.append("materialNo", materialNo)
                            .append("materialName", materialName)
                            .append("materialModel", materialModel);
                    String childMaterialNo = VtuzxUtil.getString(child, "childMaterialNo");
                    String childMaterialName = VtuzxUtil.getString(child, "childMaterialName");
                    String childMaterialModel = VtuzxUtil.getString(child, "childMaterialModel");
                    double numerator = VtuzxUtil.getDouble(child, "numerator");
                    double denominator = VtuzxUtil.getDouble(child, "denominator");
                    double scraprate = VtuzxUtil.getDouble(child, "scraprate");
                    double childCount = count * numerator / denominator * (1 + scraprate);
                    materialMap.append("childMaterialNo", childMaterialNo)
                            .append("childMaterialName", childMaterialName)
                            .append("childMaterialModel", childMaterialModel)
                            .append("denominator", denominator)
                            .append("numerator", numerator)
                            .append("count", childCount)
                            .append("taskCount", count)
                            .append("pickCount", 0)
                            .append("notPickCount", childCount);
                    materialList.add(materialMap);
                }
            }
        }


        return new VtuzxMap("materialList", materialList);
    }


    @Override
    public void createPrdTaskBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        int sort = VtuzxUtil.getInt(param, "sort");
        Map<String, Object> task = VtuzxUtil.getObject(param, "taskList");
        List<Map<String, Object>> dataList = VtuzxUtil.getObject(task, "dataList");
        String type = VtuzxUtil.getString(task, "taskType");
        List<Map<String, Object>> materialList = VtuzxUtil.getObject(param, "materialList");
        String billNo = IXqcConst.createBillNo(BillType.SCRW);
        String materialBillNo = IXqcConst.createBillNo(BillType.YLQD);
        String startTime = VtuzxUtil.getString(task, "startTime");
        String endTime = VtuzxUtil.getString(task, "endTime");
        String remark = VtuzxUtil.getString(task, "remark");
        String produceHouseName = VtuzxUtil.getString(task, "produceHouseName");
        String produceHouseNo = VtuzxUtil.getString(task, "produceHouse");

        double sumCount = 0d;
        for (Map<String, Object> data : dataList) {
            Document detail = new Document();
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialModel = VtuzxUtil.getString(data, "materialModel");
            String unit = VtuzxUtil.getString(data, "unitName");
            double count = VtuzxUtil.getDouble(data, "count");
            if (count == 0) {
                throw new VtuzxException("数量填写错误,请检查！");
            }
            sumCount += count;
            detail.append("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialModel", materialModel)
                    .append("unit", unit)
                    .append("count", count)
                    .append("billNo", billNo)
                    .append("inType", "待入库");
            prdTaskDetailDao.insertOne(detail);

            for (Map<String, Object> material : materialList) {
                String fMaterialNo = VtuzxUtil.getString(material, "materialNo");
                if ("sorting".equals(type)) {
                    Document materialDoc = new Document(material);
                    materialDoc.append("billNo", materialBillNo)
                            .append("taskBillNo", billNo);
                    materialBomDetailDao.insertOne(materialDoc);
                } else {
                    if (fMaterialNo.equals(materialNo)) {
                        Document materialDoc = new Document(material);
                        materialDoc.append("billNo", materialBillNo)
                                .append("taskBillNo", billNo);
                        materialBomDetailDao.insertOne(materialDoc);
                    }
                }
//            }
            }
        }
        ObjectId _id = prdTaskDao.insertBill(userId, userName, new Document("billNo", billNo)
                .append("materialBomBillNo", materialBillNo)
                .append("startTime", startTime)
                .append("endTime", endTime)
                .append("remark", remark)
                .append("produceHouseName", produceHouseName)
                .append("produceHouseNo", produceHouseNo)
                .append("type", type)
                .append("status", BillStatus.Save.toString())
                .append("businessStatus", "create")
                .append("sort", sort)
                .append("isPrint", "unseal")
                .append("isUpload", false)
                .append("count", sumCount));

        materialBomDao.insertBill(userId, userName, new Document("billNo", materialBillNo)
                .append("taskBillNo", billNo)
                .append("status", BillStatus.Audit.toString())
                .append("taskStatus", BillStatus.Save.toString()));


    }

    @Override
    public void auditPrdTaskBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String type = VtuzxUtil.getString(prdTaskDoc, "type");
        prdTaskDao.audit(userId, userName, billNo);
        prdTaskDao.updateOne(Criteria.where("billNo").is(billNo), new Document("businessStatus", "release"));
        materialBomDao.updateOne(Criteria.where("taskBillNo").is(billNo), new Document("taskStatus", BillStatus.Audit.toString()));
//        if ("product".equals(type)) {
//            try {
//                syncKingdeeOrderService.syncPrdOrder(userId, userName, billNo, "pda");
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
//        }
    }

    @Override
    public VtuzxMap getPrdTaskListPda(ObjectId userId, String userName, List<String> characterKeyList, Map<String, Object> param) {
        Criteria cond = new Criteria();
        if (characterKeyList.contains("cjzr")) {
            cond.and("createUserName").is(userName);
        }
        String type = VtuzxUtil.getString(param, "type");
        String inTaskBillNo = VtuzxUtil.getString(param, "billNo");
        if (!VtuzxUtil.isEmpty(inTaskBillNo)) {
            cond.and("billNo").regex(inTaskBillNo);
        }
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        cond.and("type").is(type).and("businessStatus").ne("end").and("status").ne("close");
        List<VtuzxMap> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Iterator<Document> prdTaskItr = prdTaskDao.findList(cond, new Document("status", -1).append("sort", -1).append("createTime", -1), pageIndex, pageSize);
        while (prdTaskItr.hasNext()) {
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            billNoList.add(billNo);
            VtuzxMap prdTaskMap = new VtuzxMap(prdTaskDoc);
            prdTaskMap.append("id", VtuzxUtil.removeString(prdTaskMap, IVtuzxConst.Key__id));
            dataList.add(prdTaskMap);
        }

        List<String> taskBillNoList = new ArrayList<>();
        Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").in(billNoList).and("task").is(true), null, 0, 0);
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
            taskBillNoList.add(taskBillNo);
        }

        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            if (taskBillNoList.contains(billNo)) {
                data.append("inStock", true);
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdTaskListWeb(ObjectId userId, String userName, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String type = VtuzxUtil.getString(param, "type");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String produceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        String isUpload = VtuzxUtil.getString(param, "isUpload");
        String status = VtuzxUtil.getString(param, "status");
        Integer pickStauts = VtuzxUtil.getInt(param, "pickStatus");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        if (!VtuzxUtil.isEmpty(isUpload)) {
            boolean isUploadBoo = Boolean.parseBoolean(isUpload);
            cond.and("isUpload").is(isUploadBoo);
        }

        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(pickStauts) && pickStauts != 0) {

            if (pickStauts == 1) {
                cond.and("pickStatus").is(null);
            } else {
                cond.and("pickStatus").is(true);
            }

        }
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("type").is(type);
        }
        if (!VtuzxUtil.isEmpty(produceHouseName)) {
            cond.and("produceHouseName").is(produceHouseName);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(materialNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            Iterator<Document> materialBomPickDetailItr = prdTaskDetailDao.findList(pickCond, new Document("createTime", -1), 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdTaskDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdTaskDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        List<String> taskBillNoList = new ArrayList<>();
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> {
            VtuzxMap data = new VtuzxMap(doc);
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            taskBillNoList.add(taskBillNo);
            data.append("id", VtuzxUtil.removeString(data, "_id"));
            data.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "createTime")));
            data.append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "auditTime")));
            return data;
        });


        List<String> prdColList = new ArrayList<>();
        List<VtuzxMap> prdColBillNoList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").in(taskBillNoList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdColDoc = prdColItr.next();
            String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
            String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
            prdColList.add(colBillNo);
            prdColBillNoList.add(new VtuzxMap("colBillNo", colBillNo).append("taskBillNo", taskBillNo));
        }

        List<String> prdColDetailList = new ArrayList<>();
        Iterator<Document> colDetailItr = prdColDetailDao.findList(Criteria.where("billNo").in(prdColList).and("noPrint").is(false), null, 0, 0);
        while (colDetailItr.hasNext()) {
            Document colDetailDoc = colDetailItr.next();
            String detailColBillNo = VtuzxUtil.getString(colDetailDoc, "billNo");
            for (VtuzxMap prdColBillNo : prdColBillNoList) {
                String colBillNo = VtuzxUtil.getString(prdColBillNo, "colBillNo");
                String taskBillNo = VtuzxUtil.getString(prdColBillNo, "taskBillNo");
                if (detailColBillNo.equals(colBillNo)) {
                    prdColDetailList.add(taskBillNo);
                }
            }
        }

        for (VtuzxMap data : dataList) {
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            for (String prdColDetail : prdColDetailList) {
                if (taskBillNo.equals(prdColDetail)) {
                    data.append("isPrint", true);
                }
            }
        }

//                new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
//                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
//                .append("startTime", VtuzxUtil.getString(doc, "startTime"))
//                .append("endTime", VtuzxUtil.getString(doc, "endTime"))
//                .append("businessStatus", VtuzxUtil.getString(doc, "businessStatus"))
//                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
//                .append("status", VtuzxUtil.getString(doc, "status"))
//                .append("type", VtuzxUtil.getString(doc, "type"))
//                .append("pickStatus", VtuzxUtil.getBoolean(doc, "pickStatus"))
//                .append("count", VtuzxUtil.getDouble(doc, "count"))
//                .append("_createUserId", VtuzxUtil.getString(doc, "_createUserId"))
//                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
//                .append("_auditUserId", VtuzxUtil.getString(doc, "_auditUserId"))
//                .append("auditUserName", VtuzxUtil.getString(doc, "auditUserName"))
//                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
//                .append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "auditTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    // 根据用户ID、用户名和参数获取生产任务列表
    public VtuzxMap getPrdTaskListWebBn(ObjectId userId, String userName, Map<String, Object> param) {
        // 获取参数中的billNo
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 获取参数中的type
        String type = VtuzxUtil.getString(param, "type");
        // 获取参数中的materialNo
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        // 获取参数中的produceHouseName
        String produceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        // 获取参数中的createUserName
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        // 获取参数中的isPrint
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        // 获取参数中的isUpload
        String isUpload = VtuzxUtil.getString(param, "isUpload");
        // 获取参数中的status
        String status = VtuzxUtil.getString(param, "status");
        // 获取参数中的pickStatus
        Integer pickStauts = VtuzxUtil.getInt(param, "pickStatus");
        // 获取参数中的createTime
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        // 获取参数中的pageSize
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        // 获取参数中的pageIndex
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        // 创建副本用于内部处理
        String searchBillNo = billNo;
        // 创建查询条件
        Criteria cond = new Criteria();
        // 如果状态不为空，则添加状态查询条件
        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        // 如果上传状态不为空，则添加上传状态查询条件
        if (!VtuzxUtil.isEmpty(isUpload)) {
            boolean isUploadBoo = Boolean.parseBoolean(isUpload);
            cond.and("isUpload").is(isUploadBoo);
        }
        // 如果单号不为空，则添加单号查询条件
        /*if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }*/
        // 如果领料状态不为空，则添加领料状态查询条件
        // 判断pickStauts是否为空且不等于0
        if (!VtuzxUtil.isEmpty(pickStauts) && pickStauts != 0) {
            // 如果pickStauts等于1，则将pickStatus字段设置为null
            if (pickStauts == 1) {
                cond.and("pickStatus").is(null);
            } else {
                // 否则将pickStatus字段设置为true
                cond.and("pickStatus").is(true);
            }
        }
        // 如果类型不为空，则添加类型查询条件
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("type").is(type);
        }
        // 如果生产车间不为空，则添加生产车间查询条件
        if (!VtuzxUtil.isEmpty(produceHouseName)) {
            cond.and("produceHouseName").is(produceHouseName);
        }
        // 如果创建用户不为空，则添加创建用户查询条件
        // 判断createUserName是否为空
        if (!VtuzxUtil.isEmpty(createUserName)) {
            // 将createUserName按"，"分割成数组
            String[] splitList = createUserName.split("，");
            // 如果分割后的数组长度为1，则使用regex方法进行模糊匹配
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
                // 否则将数组转成list，并使用in方法进行in查询
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        // 如果创建时间不为空，则添加创建时间查询条件
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        // 只查询有BN开头的任务
        Set<String> bnTaskBillNos = new HashSet<>();
        {
            // 查询所有批次号以BN开头的领料单详情
            Criteria detailBatchCriteria = Criteria.where("batchNo").regex("^BN");
            // 获取所有符合条件的领料单详情
            Iterator<Document> bnDetailItr = materialBomPickDetailDao.findList(detailBatchCriteria, null, 0, 0);
            // 创建一个集合，用于存储领料单号
            Set<String> pickBillNos = new HashSet<>();
            // 遍历所有符合条件的领料单详情
            while (bnDetailItr.hasNext()) {
                // 获取当前领料单详情
                Document doc = bnDetailItr.next();
                // 将领料单号添加到集合中
                pickBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            // 通过领料单号查询对应的生产任务单号
            // 如果pickBillNos不为空
            if (!pickBillNos.isEmpty()) {
                // 从materialBomPickDao中查找满足条件的Document
                Iterator<Document> pickBillItr = materialBomPickDao.findList(Criteria.where("billNo").in(pickBillNos), null, 0, 0);
                // 遍历查找结果
                while (pickBillItr.hasNext()) {
                    // 获取下一个Document
                    Document doc = pickBillItr.next();
                    // 将taskBillNo添加到bnTaskBillNos中
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
            // 补料单处理
            Criteria suppBatchCriteria = Criteria.where("batchNo").regex("^BN");
            Iterator<Document> bnSuppDetailItr = materialBomSupplementDetailDao.findList(suppBatchCriteria, null, 0, 0);
            Set<String> suppBillNos = new HashSet<>();
            while (bnSuppDetailItr.hasNext()) {
                Document doc = bnSuppDetailItr.next();
                suppBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            if (!suppBillNos.isEmpty()) {
                Iterator<Document> suppBillItr = materialBomSupplementDao.findList(Criteria.where("billNo").in(suppBillNos), null, 0, 0);
                while (suppBillItr.hasNext()) {
                    Document doc = suppBillItr.next();
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
            // 入库单处理
            Criteria inBatchCriteria = Criteria.where("batchNo").regex("^BN");
            Iterator<Document> bnInDetailItr = prdInDetailDao.findList(inBatchCriteria, null, 0, 0);
            Set<String> inBillNos = new HashSet<>();
            while (bnInDetailItr.hasNext()) {
                Document doc = bnInDetailItr.next();
                inBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            if (!inBillNos.isEmpty()) {
                Iterator<Document> inBillItr = prdInDao.findList(Criteria.where("billNo").in(inBillNos), null, 0, 0);
                while (inBillItr.hasNext()) {
                    Document doc = inBillItr.next();
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
        }
        if (!VtuzxUtil.isEmpty(searchBillNo)) {
            // 转义正则特殊字符
            String escapedBillNo = Pattern.quote(searchBillNo.trim());
            Pattern pattern = Pattern.compile(".*" + escapedBillNo + ".*", Pattern.CASE_INSENSITIVE);
            // 保留匹配billNo的BN单号
            bnTaskBillNos = bnTaskBillNos.stream()
                    .filter(bn -> bn != null && pattern.matcher(bn).find())
                    .collect(Collectors.toSet());
        }
        // 如果bnTaskBillNos不为空
        if (!bnTaskBillNos.isEmpty()) {
            // 添加条件，billNo在bnTaskBillNos中
            cond.and("billNo").in(bnTaskBillNos);
        } else {
            return new VtuzxMap(IVtuzxConst.Key_total, 0).append(IVtuzxConst.Key_data, new ArrayList<>());
        }
        // 如果materialNo不为空且billNo为空
        if (!VtuzxUtil.isEmpty(materialNo) && VtuzxUtil.isEmpty(billNo)) {
            // 创建一个空的pickBillNoList列表
            List<String> pickBillNoList = new ArrayList<>();
            // 创建一个空的pickCond条件
            Criteria pickCond = new Criteria();
            // 如果materialNo不为空，则将materialNo添加到pickCond条件中
            /*if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }*/
            // 将batchNo以BN开头的条件添加到pickCond条件中
            pickCond.and("batchNo").regex("^BN");
            // 根据pickCond条件查询materialBomPickDetailItr
            Iterator<Document> materialBomPickDetailItr = prdTaskDetailDao.findList(pickCond, new Document("createTime", -1), 0, 0);
            // 遍历materialBomPickDetailItr
            while (materialBomPickDetailItr.hasNext()) {
                // 获取materialBomPickDetailDoc
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                // 获取pickBillNo
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                // 如果pickBillNoList中不包含pickBillNo，则将pickBillNo添加到pickBillNoList中
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            // 物料预过滤
            if (!VtuzxUtil.isEmpty(materialNo)) {
                //仅保留包含该物料的单据
                String searchMaterialNo = materialNo;
                pickBillNoList = pickBillNoList.stream()
                        .filter(tempBillNo -> {
                            Iterator<Document> matItr = prdTaskDetailDao.findList(
                                    Criteria.where("billNo").is(tempBillNo)
                                            .and("materialNo").is(searchMaterialNo),
                                    null, 0, 0
                            );
                            return matItr.hasNext();
                        })
                        .collect(Collectors.toList());
            }
            if (pickBillNoList.isEmpty()) {
                return new VtuzxMap(IVtuzxConst.Key_total, 0)
                        .append(IVtuzxConst.Key_data, new ArrayList<>());
            }
            // 创建一个空的pickList列表
            List<VtuzxMap> pickList = new ArrayList<>();
            // 根据cond条件查询materialBomPickCount
            long materialBomPickCount = prdTaskDao.count(cond.and("billNo").in(pickBillNoList));
            // 根据cond条件查询materialBomPickItr
            Iterator<Document> materialBomPickItr = prdTaskDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            // 遍历materialBomPickItr
            while (materialBomPickItr.hasNext()) {
                // 获取materialBomPickDoc
                Document materialBomPickDoc = materialBomPickItr.next();
                // 创建一个materialBomPickMap
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                // 将id添加到materialBomPickMap中
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                // 将createTime添加到materialBomPickMap中
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                // 将materialBomPickMap添加到pickList中
                pickList.add(materialBomPickMap);
            }
            // 返回一个包含total和data的VtuzxMap
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        // 获取生产任务列表
        // 创建一个String类型的列表，用于存储任务单号
        List<String> taskBillNoList = new ArrayList<>();
        Iterator<Document> bnItr = prdTaskDao.findList(Criteria.where("billNo").in(bnTaskBillNos),null, 0, 0);
        while (bnItr.hasNext()) {
            // 获取当前遍历到的Document对象
            Document prdBnDoc = bnItr.next();
            // 从Document对象中获取billNo和taskBillNo
            String colBillNo = VtuzxUtil.getString(prdBnDoc, "billNo");
            String taskBillNo = VtuzxUtil.getString(prdBnDoc, "billNo");
            String typeBill = VtuzxUtil.getString(prdBnDoc, "type");
            Date createTimeBill = VtuzxUtil.getObject(prdBnDoc, "createTime");
        }
        // 根据条件、排序方式、页码、每页显示的条数，从数据库中查询数据
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        // 遍历查询结果，对每个数据项进行处理
        List<VtuzxMap> dataList = page.iterator(doc -> {
            // 将查询结果转换为VtuzxMap类型
            VtuzxMap data = new VtuzxMap(doc);
            // 从数据项中获取任务单号，并将其添加到taskBillNoList列表中
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            taskBillNoList.add(taskBillNo);
            // 将_id字段从数据项中移除，并将其添加到id字段中
            data.append("id", VtuzxUtil.removeString(data, "_id"));
            // 将createTime字段从数据项中移除，并将其格式化为指定格式，然后添加到createTime字段中
            data.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "createTime")));
            // 将auditTime字段从数据项中移除，并将其格式化为指定格式，然后添加到auditTime字段中
            data.append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "auditTime")));
            // 返回处理后的数据项
            return data;
        });
        // 创建一个String类型的List，用于存储prdCol集合中的billNo
        List<String> prdColList = new ArrayList<>();
        // 创建一个VtuzxMap类型的List，用于存储prdCol集合中的billNo和taskBillNo
        List<VtuzxMap> prdColBillNoList = new ArrayList<>();
        // 使用Criteria查询prdCol集合，条件为taskBillNo在taskBillNoList中，并且不指定排序和分页
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").in(taskBillNoList), null, 0, 0);
        // 遍历查询结果
        while (prdColItr.hasNext()) {
            // 获取当前遍历到的Document对象
            Document prdColDoc = prdColItr.next();
            // 从Document对象中获取billNo和taskBillNo
            String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
            String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
            // 将billNo添加到prdColList中
            prdColList.add(colBillNo);
            // 将billNo和taskBillNo添加到prdColBillNoList中
            prdColBillNoList.add(new VtuzxMap("colBillNo", colBillNo).append("taskBillNo", taskBillNo));
        }
        // 创建一个字符串类型的列表
        List<String> prdColDetailList = new ArrayList<>();
        // 从prdColDetailDao中查找符合条件的数据，返回一个迭代器
        Iterator<Document> colDetailItr = prdColDetailDao.findList(Criteria.where("billNo").in(prdColList).and("noPrint").is(false), null, 0, 0);
        // 遍历迭代器中的数据
        while (colDetailItr.hasNext()) {
            // 获取迭代器中的下一个数据
            Document colDetailDoc = colDetailItr.next();
            // 获取billNo字段的值
            String detailColBillNo = VtuzxUtil.getString(colDetailDoc, "billNo");
            // 遍历prdColBillNoList中的数据
            for (VtuzxMap prdColBillNo : prdColBillNoList) {
                // 获取colBillNo字段的值
                String colBillNo = VtuzxUtil.getString(prdColBillNo, "colBillNo");
                // 获取taskBillNo字段的值
                String taskBillNo = VtuzxUtil.getString(prdColBillNo, "taskBillNo");
                // 如果detailColBillNo等于colBillNo，则将taskBillNo添加到prdColDetailList中
                if (detailColBillNo.equals(colBillNo)) {
                    prdColDetailList.add(taskBillNo);
                }
            }
        }
        // 判断是否打印
        // 遍历dataList中的每一个data
        for (VtuzxMap data : dataList) {
            // 获取data中的billNo字段值
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            // 遍历prdColDetailList中的每一个prdColDetail
            for (String prdColDetail : prdColDetailList) {
                // 如果taskBillNo等于prdColDetail
                if (taskBillNo.equals(prdColDetail)) {
                    // 将data中的isPrint字段值设置为true
                    data.append("isPrint", true);
                }
            }
        }
        // 返回结果
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdTaskDetail(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        boolean pda = VtuzxUtil.getBoolean(param, "pda");
        String type = VtuzxUtil.getString(param, "type");
        boolean inStock = VtuzxUtil.getBoolean(param, "inStock");
        String billNo = VtuzxUtil.getString(param, "billNo");
        if (pda && inStock || "return".equals(type) || "supplement".equals(type)) {
            Document pickedDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
            if (VtuzxUtil.isEmpty(pickedDoc)) {
                throw new VtuzxException("订单未领料");
            }
            String status = VtuzxUtil.getString(pickedDoc, "status");
            if ("save".equals(status)) {
                throw new VtuzxException("订单领料未审核");
            }
        }
        List<VtuzxMap> dataList = new ArrayList<>();
        Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
        double pickCount = 0d;
        if (!VtuzxUtil.isEmpty(pickDoc)) {
            pickCount = VtuzxUtil.getDouble(pickDoc, "count");
        }
        String pickBillNo = VtuzxUtil.getString(pickDoc,"billNo");
        Iterator<Document> pickDetailItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(pickBillNo),null,0,0);
        List<Document> pickDetailList = new ArrayList<>();//领料详情集合
        while (pickDetailItr.hasNext()){
            Document pickDetailDoc = pickDetailItr.next();
            pickDetailList.add(pickDetailDoc);
        }

        double supplementCount = 0d;
        List<String> feedNoList = new ArrayList<>();
        Iterator<Document> materialBomSupplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        while (materialBomSupplementItr.hasNext()) {
            Document supplementDoc = materialBomSupplementItr.next();
            double count = VtuzxUtil.getDouble(supplementDoc, "count");
            String feedNo = VtuzxUtil.getString(supplementDoc, "billNo");
            supplementCount += count;
            if (!feedNoList.contains(feedNo)){
                feedNoList.add(feedNo);
            }
        }
        Iterator<Document> materialBomSupplementDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").in(feedNoList),null,0,0);

        List<Document> feedDetailList = new ArrayList<>();//领料详情集合
        while (materialBomSupplementDetailItr.hasNext()){
            Document feedDetailDoc = materialBomSupplementDetailItr.next();
            feedDetailList.add(feedDetailDoc);
        }
        List<String> prdInBillNoList = new ArrayList<>();
        Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String prdInBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            prdInBillNoList.add(prdInBillNo);
        }
        VtuzxMap prdInMap = new VtuzxMap();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(prdInBillNoList), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDoc = prdInDetailItr.next();
            String materialNo = VtuzxUtil.getString(prdInDoc, "materialNo");
            double count = VtuzxUtil.getDouble(prdInDoc, "count");
            double sumCount = VtuzxUtil.getDouble(prdInMap, materialNo);
            if (sumCount == 0) {
                prdInMap.append(materialNo, count);
            } else {
                prdInMap.remove(materialNo);
                prdInMap.append(materialNo, sumCount + count);
            }
        }
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        //获取当前任务时间添加任务编号
        Date createTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        //把date转换成localdateTime获取当天开始时间和结束时间
        Instant instant = createTime.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String taskBillNo = VtuzxUtil.getString(map, "billNo");
            if (billNo.equals(taskBillNo)) {
                break;
            }
        }
        if (VtuzxUtil.isEmpty(prdTaskDoc)) {
            throw new VtuzxException("不存在的生产任务");
        }
        if (pda) {
            String status = VtuzxUtil.getString(prdTaskDoc, "status");
            if ("close".equals(status)) {
                throw new VtuzxException("任务已关闭");
            }
        }
        double userCount = 0d;
        Iterator<Document> prdColDetailDocItr = prdColDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("isTemp").is(true), null, 0, 0);
        while (prdColDetailDocItr.hasNext()) {
            Document prdColDetailDoc = prdColDetailDocItr.next();
            List<String> traceBackList = VtuzxUtil.getObject(prdColDetailDoc, "traceBack");
            if (userId.equals(VtuzxUtil.getObject(prdColDetailDoc, "_insertUserId"))) {
                userCount += traceBackList.size();
            }
        }

        VtuzxMap header = new VtuzxMap(prdTaskDoc);
        header.append("id", VtuzxUtil.removeString(header, IVtuzxConst.Key__id))
                .append("pickedCount", String.format("%.2f", pickCount + supplementCount))
                .append("orderNum", orderNum)
                .append("bnBom", false)
                .append("notBn", false)
                .append("userCount", userCount);//任务序号
        header.replace("count", String.format("%.2f", VtuzxUtil.getDouble(header, "count")));

        for (Document pick : pickDetailList){
            String batchNo = VtuzxUtil.getString(pick,"batchNo");
            if (batchNo.startsWith("BN")){
                header.append("bnBom",true);
            } else {
                header.append("notBn",true);
            }
        }
        if (!VtuzxUtil.isEmpty(feedDetailList)){
            for (Document pick : feedDetailList){
                String batchNo = VtuzxUtil.getString(pick,"batchNo");
                if (batchNo.startsWith("BN")){
                    header.append("bnBom",true);
                } else {
                    header.append("notBn",true);
                }
            }
        }


        Iterator<Document> prdTaskDetailItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdTaskDetailItr.hasNext()) {
            Document prdTaskDetailDoc = prdTaskDetailItr.next();
//            String materialNo = VtuzxUtil.getString(prdTaskDetailDoc, "materialNo");
//            materialNoList.add(materialNo);
            VtuzxMap prdTaskDetailMap = new VtuzxMap(prdTaskDetailDoc);
            prdTaskDetailMap.append("id", VtuzxUtil.removeString(prdTaskDetailMap, IVtuzxConst.Key__id));
            prdTaskDetailMap.append("unitName", VtuzxUtil.removeString(prdTaskDetailMap, "unit"));
            dataList.add(prdTaskDetailMap);
        }
        //查物料单位 但还没用上
//        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
//        while (materialItr.hasNext()) {
//            Document materialDoc = materialItr.next();
//            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
//        }
        for (VtuzxMap data : dataList) {
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            data.append("prdInCount", VtuzxUtil.getString(prdInMap, materialNo));
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("header", header);
    }

    @Override
    // 根据用户ID、用户名和参数获取生产任务详情
    public VtuzxMap getPrdTaskDetailBn(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        // 获取参数中的pda值，并转换为布尔类型
        boolean pda = VtuzxUtil.getBoolean(param, "pda");
        // 获取参数中的type值，并转换为字符串类型
        String type = VtuzxUtil.getString(param, "type");
        // 获取参数中的inStock值，并转换为布尔类型
        boolean inStock = VtuzxUtil.getBoolean(param, "inStock");
        // 获取参数中的billNo值，并转换为字符串类型
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 如果pda为true且inStock为true，或者type为return或者type为supplement
        if (pda && inStock || "return".equals(type) || "supplement".equals(type)) {
            // 根据taskBillNo查询领料单
            Document pickedDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
            // 如果领料单为空，抛出异常
            if (VtuzxUtil.isEmpty(pickedDoc)) {
                throw new VtuzxException("订单未领料");
            }
            // 获取领料单的状态
            String status = VtuzxUtil.getString(pickedDoc, "status");
            // 如果状态为save，抛出异常
            if ("save".equals(status)) {
                throw new VtuzxException("订单领料未审核");
            }
        }
        // 创建一个List对象，用于存储VtuzxMap类型的元素
        List<VtuzxMap> dataList = new ArrayList<>();
        // 从materialBomPickDao中查询taskBillNo为billNo的Document对象
        Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
        // 初始化pickCount为0d
        double pickCount = 0d;
        // 如果pickDoc不为空
        if (!VtuzxUtil.isEmpty(pickDoc)) {
            // 从pickDoc中获取count字段的值，并将其转换为double类型赋值给pickCount
            pickCount = VtuzxUtil.getDouble(pickDoc, "count");
        }
        // 定义一个double类型的变量supplementCount，初始值为0
        double supplementCount = 0d;
        // 使用Criteria.where方法查询materialBomSupplementDao中taskBillNo为billNo的记录，并返回一个Iterator<Document>类型的迭代器
        Iterator<Document> materialBomSupplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        // 遍历迭代器
        while (materialBomSupplementItr.hasNext()) {
            // 获取迭代器中的下一个Document对象
            Document supplementDoc = materialBomSupplementItr.next();
            // 使用VtuzxUtil工具类中的getDouble方法获取supplementDoc中count字段的值，并赋值给double类型的变量count
            double count = VtuzxUtil.getDouble(supplementDoc, "count");
            // 将count的值累加到supplementCount中
            supplementCount += count;
        }
        // 创建一个空的字符串列表，用于存储产品入库单号
        List<String> prdInBillNoList = new ArrayList<>();
        // 查询产品入库列表，根据任务单号查询，返回一个迭代器
        Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        // 遍历迭代器
        while (prdInItr.hasNext()) {
            // 获取下一个产品入库文档
            Document prdInDoc = prdInItr.next();
            // 从文档中获取产品入库单号
            String prdInBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            // 将产品入库单号添加到列表中
            prdInBillNoList.add(prdInBillNo);
        }
        // 创建一个VtuzxMap对象
        VtuzxMap prdInMap = new VtuzxMap();
        // 根据billNo字段查询prdInDetailDao中的数据，返回一个Iterator
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(prdInBillNoList), null, 0, 0);
        // 遍历Iterator
        while (prdInDetailItr.hasNext()) {
            // 获取下一个Document对象
            Document prdInDoc = prdInDetailItr.next();
            // 获取materialNo字段的值
            String materialNo = VtuzxUtil.getString(prdInDoc, "materialNo");
            // 获取count字段的值
            double count = VtuzxUtil.getDouble(prdInDoc, "count");
            // 获取prdInMap中materialNo字段的值
            double sumCount = VtuzxUtil.getDouble(prdInMap, materialNo);
            // 如果sumCount为0，则将materialNo和count添加到prdInMap中
            if (sumCount == 0) {
                prdInMap.append(materialNo, count);
                // 否则，将materialNo从prdInMap中移除，并将materialNo和sumCount+count添加到prdInMap中
            } else {
                prdInMap.remove(materialNo);
                prdInMap.append(materialNo, sumCount + count);
            }
        }
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        //获取当前任务时间添加任务编号
        Date createTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        //把date转换成localdateTime获取当天开始时间和结束时间
        // 将createTime转换为Instant类型
        Instant instant = createTime.toInstant();
        // 获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();
        // 将Instant类型转换为LocalDateTime类型
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        // 将LocalDateTime类型转换为当天的开始时间
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        // 将LocalDateTime类型转换为当天的结束时间
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        // 创建一个VtuzxMap类型的列表
        List<VtuzxMap> dayList = new ArrayList<>();
        // 创建一个Criteria对象
        Criteria cond = new Criteria();
        // 设置查询条件，查询createTime在localStartTime和localEndTime之间的数据
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        // 从prdTaskDao中查询符合条件的列表，按照createTime升序排列
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        // 遍历查询结果
        while (prdColDayItr.hasNext()) {
            // 获取查询结果中的Document对象
            Document prdColDoc = prdColDayItr.next();
            // 将Document对象转换为VtuzxMap对象
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            // 将VtuzxMap对象添加到列表中
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0; // 定义一个变量orderNum，用于记录循环次数
        for (VtuzxMap map : dayList) { // 遍历dayList中的每一个VtuzxMap对象
            orderNum++; // 每循环一次，orderNum加1
            String taskBillNo = VtuzxUtil.getString(map, "billNo"); // 获取当前VtuzxMap对象的"billNo"字段的值
            if (billNo.equals(taskBillNo)) { // 如果当前VtuzxMap对象的"billNo"字段的值与billNo相等
                break; // 则跳出循环
            }
        }
        // 判断prdTaskDoc是否为空，如果为空则抛出异常
        if (VtuzxUtil.isEmpty(prdTaskDoc)) {
            throw new VtuzxException("不存在的生产任务");
        }
        // 如果pda为真，则获取prdTaskDoc中的status字段，如果status为close，则抛出异常
        // 如果pda为true
        if (pda) {
            // 获取prdTaskDoc中的status字段
            String status = VtuzxUtil.getString(prdTaskDoc, "status");
            // 如果status为"close"
            if ("close".equals(status)) {
                // 抛出任务已关闭的异常
                throw new VtuzxException("任务已关闭");
            }
        }
        //声明一个double类型的变量，初始值为0
        double userCount = 0d;
        //根据条件查询prdColDetailDao中的数据，并返回一个迭代器
        Iterator<Document> prdColDetailDocItr = prdColDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("isTemp").is(true), null, 0, 0);
        //遍历迭代器中的数据
        while (prdColDetailDocItr.hasNext()) {
            //获取迭代器中的下一个数据
            Document prdColDetailDoc = prdColDetailDocItr.next();
            //从prdColDetailDoc中获取traceBack数据
            List<String> traceBackList = VtuzxUtil.getObject(prdColDetailDoc, "traceBack");
            //如果userId等于prdColDetailDoc中的_insertUserId，则将traceBackList的大小加到userCount上
            if (userId.equals(VtuzxUtil.getObject(prdColDetailDoc, "_insertUserId"))) {
                userCount += traceBackList.size();
            }
        }
        //将prdTaskDoc中的数据存入VtuzxMap中
        VtuzxMap header = new VtuzxMap(prdTaskDoc);
        //将header中的id替换为去除字符串后的值
        header.append("id", VtuzxUtil.removeString(header, IVtuzxConst.Key__id))
                //将header中的pickedCount替换为pickCount与supplementCount之和，并保留两位小数
                .append("pickedCount", String.format("%.2f", pickCount + supplementCount))
                //将header中的orderNum替换为orderNum
                .append("orderNum", orderNum)
                //将header中的userCount替换为userCount
                .append("userCount", userCount);//任务序号
        //将header中的count替换为去除字符串后的值，并保留两位小数
        // 将header中的count字段替换为保留两位小数的浮点数
        header.replace("count", String.format("%.2f", VtuzxUtil.getDouble(header, "count")));
        // 根据billNo查询prdTaskDetailDao中的数据
        Iterator<Document> prdTaskDetailItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        // 遍历查询结果
        while (prdTaskDetailItr.hasNext()) {
            // 获取下一个Document对象
            Document prdTaskDetailDoc = prdTaskDetailItr.next();
            // 将Document对象转换为VtuzxMap对象
            VtuzxMap prdTaskDetailMap = new VtuzxMap(prdTaskDetailDoc);
            // 去除VtuzxMap对象中的id字段
            prdTaskDetailMap.append("id", VtuzxUtil.removeString(prdTaskDetailMap, IVtuzxConst.Key__id));
            // 去除VtuzxMap对象中的unit字段
            prdTaskDetailMap.append("unitName", VtuzxUtil.removeString(prdTaskDetailMap, "unit"));
            // 将VtuzxMap对象添加到dataList中
            dataList.add(prdTaskDetailMap);
        }
        // 创建一个Set，用于存放batchNo以BN开头的materialNo
        Set<String> bnMaterialNos = new HashSet<>();
        // 创建一个Criteria，用于查询batchNo以BN开头的记录
        {
            Criteria detailBatchCriteria = Criteria.where("batchNo").regex("^BN");
            // 查询符合条件的记录
            Iterator<Document> bnDetailItr = materialBomPickDetailDao.findList(detailBatchCriteria, null, 0, 0);
            // 遍历查询结果
            while (bnDetailItr.hasNext()) {
                // 将查询结果中的materialNo添加到Set中
                bnMaterialNos.add(VtuzxUtil.getString(bnDetailItr.next(), "materialNo"));
            }
        }
        // 过滤dataList，只保留materialNo在bnMaterialNos中的记录
        dataList = dataList.stream()
                .filter(data -> bnMaterialNos.contains(VtuzxUtil.getString(data, "materialNo")))
                .collect(Collectors.toList());
        // 遍历dataList
        for (VtuzxMap data : dataList) {
            // 获取当前记录的materialNo
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            // 将prdInMap中对应的值添加到当前记录中
            data.append("prdInCount", VtuzxUtil.getString(prdInMap, materialNo));
        }
        // 返回结果，包括dataList和header
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("header", header);
    }

    @Override
    public VtuzxMap getMaterialBomListPda(ObjectId userId, String userName, Map<String, Object> param) {
        List<ObjectId> ids = new ArrayList<>();
        List<VtuzxMap> dataList = new ArrayList<>();
        List<VtuzxMap> materialBomDataList = new ArrayList<>();
        Iterator<Document> materialBomItr = materialBomDao.findList(null, null, 0, 0);
        while (materialBomItr.hasNext()) {
            Document materialBomDoc = materialBomItr.next();
            VtuzxMap materialBomMap = new VtuzxMap(materialBomDoc);
            ObjectId id = VtuzxUtil.getObject(materialBomMap, IVtuzxConst.Key__id);
            ids.add(id);
            materialBomMap.append("id", VtuzxUtil.removeString(materialBomMap, IVtuzxConst.Key__id));
            materialBomDataList.add(materialBomMap);
        }

        List<VtuzxMap> materialBomDetailDataList = new ArrayList<>();
        Iterator<Document> materialBomDetailItr = materialBomDetailDao.findList(Criteria.where("_detailId").in(ids), null, 0, 0);
        while (materialBomDetailItr.hasNext()) {
            Document materialBomDetailDoc = materialBomDetailItr.next();
            VtuzxMap materialBomDetailMap = new VtuzxMap(materialBomDetailDoc);
            materialBomDetailMap.append("id", VtuzxUtil.removeString(materialBomDetailMap, "_id"));
            materialBomDetailMap.append("detailId", VtuzxUtil.removeString(materialBomDetailMap, "_detailId"));
            materialBomDetailDataList.add(materialBomDetailMap);
        }

        for (VtuzxMap materialBomData : materialBomDataList) {
            boolean add = false;
            String id = VtuzxUtil.getString(materialBomData, "id");
            for (VtuzxMap materialBomDetailData : materialBomDetailDataList) {
                String detailId = VtuzxUtil.getString(materialBomDetailData, "detailId");
                if (id.equals(detailId)) {
                    double notPickCount = VtuzxUtil.getDouble(materialBomDetailData, "notPickCount");
                    if (notPickCount > 0) {
                        add = true;
                    }
                }
            }
            if (add) {
                dataList.add(materialBomData);
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomListWeb(ObjectId userId, String userName, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        VtuzxPage page = materialBomDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("taskStatus", VtuzxUtil.getString(doc, "taskStatus"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("_createUserId", VtuzxUtil.getString(doc, "_createUserId"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomDetail(ObjectId userId, String userName, Map<String, Object> param) {
        List<VtuzxMap> dataList = new ArrayList<>();
        String billNo = VtuzxUtil.getString(param, "billNo");

        Document materialBomDoc = materialBomDao.findOne(Criteria.where("billNo").is(billNo));
        String taskBillNo = VtuzxUtil.getString(materialBomDoc, "taskBillNo");

        long count = materialBomPickDao.count(Criteria.where("taskBillNo").is(taskBillNo));

        VtuzxMap header = new VtuzxMap(materialBomDoc);
        header.append("id", VtuzxUtil.removeString(header, IVtuzxConst.Key__id));
        Date createTime = VtuzxUtil.getObject(header, "createTime");
        header.remove("createTime");
        header.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
        if (count > 0) {
            header.append("picked", true);
        } else {
            header.append("picked", false);
        }

        boolean picked = false;
        Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
        if (!VtuzxUtil.isEmpty(pickDoc)) {
            picked = true;
        }

        Iterator<Document> materialBomDetailItr = materialBomDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomDetailItr.hasNext()) {
            Document materialBomDetailDoc = materialBomDetailItr.next();
            VtuzxMap materialBomDetailMap = new VtuzxMap(materialBomDetailDoc);
            materialBomDetailMap.append("id", VtuzxUtil.removeString(materialBomDetailMap, IVtuzxConst.Key__id));
            dataList.add(materialBomDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("header", header).append("picked", picked);
    }

    @Override
    public VtuzxMap getMaterialBomBox(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");

        List<VtuzxMap> batchNoList = new ArrayList<>();
        List<String> materialNoList = new ArrayList<>();
        Iterator<Document> materialBomDetailItr = materialBomDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomDetailItr.hasNext()) {
            VtuzxMap map = new VtuzxMap();
            Document materialBomDetailDoc = materialBomDetailItr.next();
            map.append("batchNoList", VtuzxUtil.getObject(materialBomDetailDoc, "batchNo"));
            batchNoList.add(map);
            materialNoList.add(VtuzxUtil.getString(materialBomDetailDoc, "childMaterialNo"));
        }

        boolean noBatch = false;
        VtuzxMap box = inventoryService.getMaterialBox(stockNo, boxNo);
        List<VtuzxMap> dataList = VtuzxUtil.getObject(box, "data");
        for (VtuzxMap data : dataList) {
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
//            if (!materialNoList.contains(materialNo)) {
//                throw new VtuzxException("请扫描物料清单所需物料！");
//            }
            for (VtuzxMap batch : batchNoList) {
                List<String> batchList = VtuzxUtil.getObject(batch, "batchNoList");
                if (batchList != null) {
                    for (String batchNoKey : batchList) {
                        if (batchNo.equals(batchNoKey)) {
                            noBatch = true;
                        }
                    }
                }
            }
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("noBatch", noBatch);
    }

    @Override
    public VtuzxMap getMaterialBomRfid(ObjectId userId, String userName, Map<String, Object> param) {
//        String billNo = VtuzxUtil.getString(param, "billNo");
//        String stockNo = VtuzxUtil.getString(param, "stockNo");
//        String locationNo = VtuzxUtil.getString(param, "locationNo");
//        List<String> rfidList = VtuzxUtil.getObject(param, "rfidList");
//
//        VtuzxMap box = (VtuzxMap) inventoryService.getMaterialByRfidInStock(rfidList, stockNo, locationNo);
//        List<VtuzxMap> dataList = VtuzxUtil.getObject(box, "data");

        return null;
    }

    @Override
    public VtuzxMap addMaterialBomBox(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");

        List<VtuzxMap> boxNoDateList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        for (Map<String, Object> box : boxList) {
            boxNoList.add(VtuzxUtil.getString(box, "boxNo"));
        }
        //如果箱号在别的领料单处于创建的状态应该也不让扫描
//        Iterator<Document> scanBoxDocItr = materialBomPickDetailBoxDao.findList(Criteria.where("boxNo").in(boxNoList).and("isTemp").is(true), null, 0, 0);
        Iterator<Document> scanBoxDocItr = materialBomPickDetailBoxDao.findList(new Criteria().orOperator(Criteria.where("boxNo").in(boxNoList).and("isTemp").is(true),
                Criteria.where("boxNo").in(boxNoList).and("status").is("save")), null, 0, 0);
        while (scanBoxDocItr.hasNext()) {
            Document scanDoc = scanBoxDocItr.next();
            String boxNo = VtuzxUtil.getString(scanDoc, "boxNo");
            String createUserName = VtuzxUtil.getString(scanDoc, "createUserName");
            boxNoDateList.add(new VtuzxMap(boxNo, createUserName));
        }
        if (boxNoDateList.size() != 0) {
            throw new VtuzxException("托盘中箱号已添加，请删除后重新扫描!【" + boxNoDateList.toString() + "】");
        }

        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");

        List<String> taskMaterialNoList = new ArrayList<>();
        Iterator<Document> taskItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(taskBillNo), null, 0, 0);
        while (taskItr.hasNext()) {
            Document taskDoc = taskItr.next();
            taskMaterialNoList.add(VtuzxUtil.getString(taskDoc, "materialNo"));
        }

        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(taskDoc, "type");

        for (Map<String, Object> data : boxList) {
            String stockNo = VtuzxUtil.getString(data, "stockNo");
            String locationNo = VtuzxUtil.getString(data, "locationNo");
            String boxNoKey = VtuzxUtil.getString(data, "boxNo");
            String traceBack = VtuzxUtil.getString(data, "traceBack");
            boolean isZS = VtuzxUtil.getBoolean(data, "isZS");
            String boxNo;
            if (boxNoKey.contains("|;")) {
                String[] boxValues = boxNoKey.split("\\|\\;");
                if (boxValues.length == 5) {
                    boxNo = boxNoKey;
                    boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                    boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                    boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                    boxNo = boxNo + "|;batch";
                } else {
                    boxNo = boxNoKey;
                }
            } else {
                boxNo = boxNoKey;
            }
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            if ("product".equals(type)) {
                if (taskMaterialNoList.contains(materialNo)) {
                    throw new VtuzxException(String.format("物料[%s]添加失败,不能出库任务单下达的物料", materialNo));
                }
            }
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
            String unit = VtuzxUtil.getString(data, "unit");
            double count = VtuzxUtil.getDouble(data, "count");
            int exp = VtuzxUtil.getInt(data, "exp");
            String produceDate = VtuzxUtil.getString(data, "produceDate");
            String rfid = VtuzxUtil.getString(data, "rfid");

            Criteria pickCond = new Criteria("boxNo").is(boxNo).and("isTemp").is(true);
            if (isZS) {
                pickCond.and("traceBack").is(traceBack);
            }
            Document boxMap = materialBomPickDetailBoxDao.findOne(pickCond);
            if (!VtuzxUtil.isEmpty(boxMap)) {
                String createUserName = VtuzxUtil.getString(boxMap, "createUserName");
                throw new VtuzxException("箱号已存在，请勿重复添加！【扫码人员：" + createUserName + "】");
            }

            Criteria detailCond = Criteria.where("stockNo").is(stockNo);
            detailCond.and("materialNo").is(materialNo);
            detailCond.and("batchNo").is(batchNo);
            if (!VtuzxUtil.isEmpty(billNo)) {
                detailCond.and("status").is("save");
            } else {
                detailCond.and("isTemp").is(true);
                detailCond.and("taskBillNo").is(taskBillNo);
            }
            Document detail = materialBomPickDetailDao.findOne(detailCond);
            Document updateVal = new Document();

            if (detail == null) {
                if (!VtuzxUtil.isEmpty(billNo)) {
                    updateVal.append("status", "save");
                    updateVal.append("billNo", billNo);
                } else {
                    updateVal.append("isTemp", true);
                }
                updateVal.append("stockNo", stockNo);
                updateVal.append("locationNo", locationNo);
                updateVal.append("materialNo", materialNo);
                updateVal.append("materialName", materialName);
                updateVal.append("materialSpec", materialSpec);
                updateVal.append("batchNo", batchNo);
                updateVal.append("unit", unit);
                updateVal.append("_createUserId", userId);
                updateVal.append("createUserName", userName);
                updateVal.append("boxCount", 1);
                if (isZS) {
                    updateVal.append("count", 1);
                } else {
                    updateVal.append("count", count);
                }
                updateVal.append("produceDate", produceDate);
                updateVal.append("exp", exp);
                updateVal.append("materialBomBillNo", materialBomBillNo);
                updateVal.append("taskBillNo", taskBillNo);
            } else {
                if (isZS) {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", 1));
                } else {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
                }
            }
            ObjectId _detailId;
            if (detail == null) {
                _detailId = materialBomPickDetailDao.insertOne(updateVal);
            } else {
                _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
                materialBomPickDetailDao.updateByIdRedirect(_detailId, updateVal);
            }

            Document detailBox = new Document();
            if (!VtuzxUtil.isEmpty(billNo)) {
                detailBox.append("status", "save");
                detailBox.append("billNo", billNo);
            } else {
                detailBox.append("isTemp", true);
            }
            detailBox.append("_detailId", _detailId);
            detailBox.append("materialNo", materialNo);
            detailBox.append("materialName", materialName);
            detailBox.append("materialSpec", materialSpec);
            detailBox.append("boxNo", boxNo);
            if (isZS) {
                detailBox.append("traceBack", traceBack);
                detailBox.append("isZS", true);
                detailBox.append("count", 1);
            } else {
                detailBox.append("count", count);
            }
            detailBox.append("batchNo", batchNo);
            detailBox.append("_createUserId", userId);
            detailBox.append("createUserName", userName);
            detailBox.append("stockNo", stockNo);
            detailBox.append("locationNo", locationNo);
            detailBox.append("unit", unit);
            detailBox.append("rfid", rfid);
            detailBox.append("taskBillNo", taskBillNo);
            detailBox.append("materialBomBillNo", materialBomBillNo);
            materialBomPickDetailBoxDao.insertOne(detailBox);

            if (!VtuzxUtil.isEmpty(billNo)) {
                materialBomPickDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("boxCount", 1).append("count", count)));
            }
        }

        return null;
    }

    @Override
    public VtuzxMap createMaterialBomPickBill(ObjectId userId, String userName, Map<String, Object> param) throws Exception {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String billNo = IXqcConst.createBillNo(BillType.SCLL);
        double actualCount = VtuzxUtil.getDouble(param, "actualCount");//实际领料重量
        //判断当前任务是否有领料单
        Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
        if (!VtuzxUtil.isEmpty(pickDoc)) {
            throw new VtuzxException("当前任务以领料");
        }

        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String status = VtuzxUtil.getString(prdTaskDoc,"status");
        if (!"audit".equals(status)){
            throw new VtuzxException("当前任务未审核，无法领料");
        }
        String taskUserName = "";
        ObjectId taskUserId = null;
        if (prdTaskDoc != null) {
            taskUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
            taskUserId = VtuzxUtil.getObject(prdTaskDoc, "_createUserId");
        }


        Criteria opCond = new Criteria();
        opCond.and("isTemp").is(true).and("_createUserId").is(userId).and("taskBillNo").is(taskBillNo);

        double sumCount = 0d;
        int sumBoxCount = 0;
        Iterator<Document> pickBoxItr = materialBomPickDetailBoxDao.findList(opCond, null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBox = pickBoxItr.next();
            double count = VtuzxUtil.getDouble(pickBox, "count");
            sumBoxCount++;
            sumCount += count;
        }
        //获取到多个仓库的编号
        List<String> stockNoList = new ArrayList<>();
        Iterator<Document> materialDetailItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (materialDetailItr.hasNext()) {
            Document materialDetailDoc = materialDetailItr.next();
            String stockNo = VtuzxUtil.getString(materialDetailDoc, "stockNo");
            stockNoList.add(stockNo);
        }
        materialBomPickDao.insertBill(userId, userName,
                new Document("billNo", billNo)
                        .append("taskBillNo", taskBillNo)
                        .append("status", BillStatus.Save.toString())
                        .append("boxCount", sumBoxCount)
                        .append("count", sumCount)
                        .append("produceHouse", produceHouse)
                        .append("stockNo", stockNoList.get(0))
                        .append("taskUserName", taskUserName)
                        .append("taskUserId", taskUserId)
                        .append("actualCount", actualCount)
                        .append("isPrint", "unseal"));

        try {
            Document detailUpdateVal = new Document("$set", new Document("billNo", billNo).append("status", "save"));
            detailUpdateVal.append("$unset", new Document("isTemp", 1));
            materialBomPickDetailDao.updateManyRedirect(opCond, detailUpdateVal);
            materialBomPickDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
        } catch (Exception e) {

            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            materialBomPickDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            materialBomPickDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            throw e;
        }

        return new VtuzxMap("billNo", billNo);
    }

    @Override
    public void auditMaterialBomPickBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");//领料单单号
        String headerStockNo = VtuzxUtil.getString(param, "stockNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        List<String> boxNoList = new ArrayList<>();
        List<VtuzxMap> bcBoxList = new ArrayList<>();
        List<Document> zsBoxList = new ArrayList<>();
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));

        String type = "";
        if (prdTaskDoc != null) {
            type = VtuzxUtil.getString(prdTaskDoc, "type");
        }

        List<String> stockNoList = new ArrayList<>();
        Iterator<Document> pickBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBox = pickBoxItr.next();
            String boxNo = VtuzxUtil.getString(pickBox, "boxNo");
            boolean isZS = VtuzxUtil.getBoolean(pickBox, "isZS");
            String traceBack = VtuzxUtil.getString(pickBox, "traceBack");
            String locationNo = VtuzxUtil.getString(pickBox, "locationNo");
            String stockNo = VtuzxUtil.getString(pickBox, "stockNo");
            if (!stockNoList.contains(stockNo)) {
                stockNoList.add(stockNo);
            }
            /*if (!stockNo.equals(headerStockNo)){
                throw new VtuzxException("仓库不对，请重新选择");
            }*/
            double count = VtuzxUtil.getDouble(pickBox, "count");
            String[] boxValues = boxNo.split("\\|\\;");
            if (boxValues.length == 3) {
                // 已入库包材长度为3
                bcBoxList.add(new VtuzxMap("boxNo", boxNo)
                        .append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue())
                        .append("locationNo", locationNo));
            } else {
                if (isZS) {
                    zsBoxList.add(new Document("traceBack", traceBack).append("boxNo", VtuzxUtil.getString(pickBox, "boxNo")));
                } else {
                    //查询库存判断当前箱号是否已经出库
                    double invCount = inventoryDetailDao.count(Criteria.where("stockNo").is(stockNo)
                            .and("locationNo").is(locationNo).and("boxNo").is(boxNo)
                            .and("status").is("in"));
                    if (invCount == 0) {//说明箱码已经出库
                        throw new VtuzxException(String.format("箱码:%s已经出库,请重新扫描", boxNo));
                    }
                    boxNoList.add(boxNo);
                }
            }
        }

        //判断有多少个仓库
        if (stockNoList.size() <= 1) {
            inventoryService.reduceInventory(userId, userName, BillEvent.Audit, BillType.SCLL, stockNoList.get(0), billNo, boxNoList, bcBoxList, zsBoxList);
        } else {
            for (String detailStockNo : stockNoList) {
                inventoryService.reduceInventory(userId, userName, BillEvent.Audit, BillType.SCLL, detailStockNo, billNo, boxNoList, bcBoxList, zsBoxList);
            }
        }

        //出库
//        inventoryService.reduceInventory(userId, userName, BillEvent.Audit, BillType.SCLL, headerStockNo, billNo, boxNoList, bcBoxList, zsBoxList);

        List<Document> boxList = new ArrayList<>();
        Iterator<Document> boxItr = materialBomPickDetailBoxDao.findList(Criteria.where("materialBomBillNo").is(materialBomBillNo).and("status").is("save"), null, 0, 0);
        while (boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            boxList.add(boxDoc);
        }

        List<Document> materialBomList = new ArrayList<>();
        Iterator<Document> materialBomItr = materialBomDetailDao.findList(Criteria.where("billNo").is(materialBomBillNo), null, 0, 0);
        while (materialBomItr.hasNext()) {
            Document materialBomDoc = materialBomItr.next();
            materialBomList.add(materialBomDoc);
        }

        //反写物料清单数量
        for (Document box : boxList) {
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            double docCount = VtuzxUtil.getDouble(box, "count");
            for (Document materialBom : materialBomList) {
                ObjectId id = VtuzxUtil.getObject(materialBom, "_id");
                String childMaterialNo = VtuzxUtil.getString(materialBom, "childMaterialNo");
                double notPickCount = VtuzxUtil.getDouble(materialBom, "notPickCount");
                if (materialNo.equals(childMaterialNo)) {
                    if (notPickCount > 0) {
                        materialBomDetailDao.updateByIdRedirect(id, new Document("$inc", new Document("pickCount", docCount).append("notPickCount", -docCount)));
                    }
                }
            }
        }

        //反写生产任务分录领料状态
        prdTaskDetailDao.updateOne(Criteria.where("billNo").is(taskBillNo), new Document("pickStatus", true).append("businessStatus", "start"));
        //反写生产任务开工状态
        prdTaskDao.updateOne(Criteria.where("billNo").is(taskBillNo), new Document("pick", true).append("businessStatus", "start").append("pickStatus", true).append("status", "audit"));
        //反写领料单状态
        materialBomPickDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", "audit"));
        try {
            Document detailUpdateVal = new Document("$unset", new Document("status", 1));
            materialBomPickDetailDao.updateManyRedirect(Criteria.where("billNo").is(billNo).and("status").is("save"), detailUpdateVal);
            materialBomPickDetailBoxDao.updateManyRedirect(Criteria.where("billNo").is(billNo).and("status").is("save"), detailUpdateVal);

//            try {
//                if ("product".equals(type)) {
//                    syncKingdeeOrderService.syncPrdPickOrder(userId, userName, billNo, "pda");
//                }
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
        } catch (Exception e) {
            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            materialBomPickDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            materialBomPickDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            throw e;
        }

    }

    @Override
    public VtuzxMap getUserMaterialBomPickMaterial(ObjectId userId, String stockNo, String billNo, String taskBillNo) {
        List<VtuzxMap> materialBomPickDetailList = new ArrayList<>();
        Document header = new Document();
        Criteria cond = new Criteria();
        if (VtuzxUtil.isEmpty(billNo)) {
            cond.and("_createUserId").is(userId).and("isTemp").is(true).and("taskBillNo").is(taskBillNo);
        } else {
            cond.and("billNo").is(billNo);
            header = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        }
        Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(cond, null, 0, 0);
        while (materialBomPickDetailItr.hasNext()) {
            Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
            VtuzxMap materialBomPickDetailMap = new VtuzxMap(materialBomPickDetailDoc);
            String id = VtuzxUtil.removeString(materialBomPickDetailMap, IVtuzxConst.Key__id);
            String createUserId = VtuzxUtil.removeString(materialBomPickDetailMap, "_createUserId");
            materialBomPickDetailMap.append("id", id).append("createUserId", createUserId);
            materialBomPickDetailList.add(materialBomPickDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomPickDetailList).append("header", header);
    }

    @Override
    public VtuzxMap getUserMaterialBomPickMaterialBox(ObjectId userId, String detailId) {
        List<VtuzxMap> materialBomPickDetailBoxList = new ArrayList<>();
        Iterator<Document> materialBomPickDetailBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("_createUserId").is(userId).and("_detailId").is(new ObjectId(detailId)), null, 0, 0);
        while (materialBomPickDetailBoxItr.hasNext()) {
            Document materialBomPickDetailBoxDoc = materialBomPickDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomPickDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            materialBomPickDetailBoxList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomPickDetailBoxList);
    }

    @Override
    public void deleteUserMaterialBomPickMaterial(ObjectId userId, String id) {
        Document detailDoc = materialBomPickDetailDao.findById(id);
        String billNo = VtuzxUtil.getString(detailDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            int boxCount = VtuzxUtil.getInt(detailDoc, "boxCount");
            materialBomPickDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -boxCount)));
            Document pickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
            if (VtuzxUtil.getDouble(pickDoc, "count") <= 0) {
                materialBomPickDao.deleteOne(Criteria.where("billNo").is(billNo));
            }
        }
        materialBomPickDetailDao.deleteById(FastUtil.convertId(id));
        materialBomPickDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserMaterialBomPickMaterialBox(ObjectId userId, String id) {
        Document materialBomPickDetailBoxDoc = materialBomPickDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(materialBomPickDetailBoxDoc, "_detailId");
        String billNo = VtuzxUtil.getString(materialBomPickDetailBoxDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(materialBomPickDetailBoxDoc, "count");
            materialBomPickDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -1)));
            Document pickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
            if (VtuzxUtil.getDouble(pickDoc, "count") <= 0) {
                materialBomPickDao.deleteOne(Criteria.where("billNo").is(billNo));
            }
        }
        materialBomPickDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> materialBomPickDetailBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (materialBomPickDetailBoxItr.hasNext()) {
            Document doc = materialBomPickDetailBoxItr.next();
            double materialBomPickDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = materialBomPickDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0 && total == 0) {
            materialBomPickDetailDao.deleteById(_detailId);
        } else {
            materialBomPickDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
    }

    @Override
    public VtuzxMap getMaterialBomPickBill(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").is(isPrint);
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomPickDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomPickDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = materialBomPickDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomPickDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomPickDao.findList(cond, null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = materialBomPickDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("actualCount", String.format("%.2f", VtuzxUtil.getDouble(doc, "actualCount")))//实际重量
                .append("discrepancy", String.format("%.2f", VtuzxUtil.getDouble(doc, "count") - VtuzxUtil.getDouble(doc, "actualCount")))
                .append("isPrint", VtuzxUtil.getString(doc, "isPrint"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    // 根据用户ID、参数、页码和每页条数获取物料BOM领料单
    public VtuzxMap getMaterialBomPickBillBn(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        // 获取参数中的billNo
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 获取参数中的taskBillNo
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        // 获取参数中的produceHouse
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        // 获取参数中的materialNo
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        // 获取参数中的boxNo
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        // 获取参数中的batchNo
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        // 获取参数中的createUserName
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        // 获取参数中的isPrint
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        // 获取参数中的createTime
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        // 创建条件对象
        Criteria cond = new Criteria();
        cond.and("count").ne(0);//数量等于零的不显示
        //如果taskBillNo不为空，则添加条件
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        //如果billNo不为空，则添加条件
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        //如果produceHouse不为空，则添加条件
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        //如果createUserName不为空，则添加条件
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            //如果createUserName只有一个值，则添加条件
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                //如果createUserName有多个值，则将数组转list，并添加条件
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        //如果createTime不为空，则添加条件
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        //如果isPrint不为空，则添加条件
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").is(isPrint);
        }
        //如果materialNo或batchNo不为空且billNo为空，则将pickBillNoList添加条件
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            // 创建一个空的pickBillNoList
            List<String> pickBillNoList = new ArrayList<>();
            // 创建一个Criteria对象pickCond
            Criteria pickCond = new Criteria();
            // 添加一个条件，batchNo以BN开头
            pickCond.and("batchNo").regex("^BN");
            // 如果materialNo不为空，则添加一个条件，materialNo等于materialNo
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            // 如果batchNo不为空，则添加一个条件，batchNo等于batchNo
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            // 获取物料BOM领料明细
            Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(pickCond, null, 0, 0);
            // 遍历物料BOM领料明细
            while (materialBomPickDetailItr.hasNext()) {
                // 获取物料BOM领料明细文档
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                // 获取领料单号
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                // 如果领料单号列表中不包含该领料单号，则将其添加到领料单号列表中
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            // 创建一个VtuzxMap的列表
            List<VtuzxMap> pickList = new ArrayList<>();
            // 获取满足条件的物料BOM领料数量
            long materialBomPickCount = materialBomPickDao.count(cond.and("billNo").in(pickBillNoList));
            // 获取满足条件的物料BOM领料列表
            Iterator<Document> materialBomPickItr = materialBomPickDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            // 遍历物料BOM领料列表
            while (materialBomPickItr.hasNext()) {
                // 获取下一个物料BOM领料文档
                Document materialBomPickDoc = materialBomPickItr.next();
                // 将物料BOM领料文档转换为VtuzxMap
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                // 添加id字段
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                // 添加createTime字段，格式化为"yyyy-MM-dd HH:mm:ss.SSS"格式
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                // 将转换后的VtuzxMap添加到列表中
                pickList.add(materialBomPickMap);
            }
            // 返回一个新的VtuzxMap对象，其中包含IVtuzxConst.Key_total和materialBomPickCount作为键值对，以及IVtuzxConst.Key_data和pickList作为键值对
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        // 如果boxNo不为空，billNo为空，则执行以下代码
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            // 创建一个List，用于存储pickBillNo
            List<String> pickBillNoList = new ArrayList<>();
            // 创建一个Criteria，用于查询materialBomPickDetailBoxDao
            Criteria boxCriteria = Criteria.where("boxNo").regex(boxNo).and("batchNo").regex("^BN");
            // 查询materialBomPickDetailBoxDao，返回一个Iterator
            Iterator<Document> materialBomPickDetailItr = materialBomPickDetailBoxDao.findList(boxCriteria, null, 0, 0);
            //Iterator<Document> materialBomPickDetailItr = materialBomPickDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            // 遍历Iterator
            while (materialBomPickDetailItr.hasNext()) {
                // 获取下一个Document
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                // 获取billNo
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                // 如果pickBillNoList中不包含pickBillNo，则将其添加到pickBillNoList中
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            // 创建一个List来存储查询结果
            List<VtuzxMap> pickList = new ArrayList<>();
            // 获取查询结果的总数
            long materialBomPickCount = materialBomPickDao.count(cond.and("billNo").in(pickBillNoList));
            // 获取查询结果的迭代器
            Iterator<Document> materialBomPickItr = materialBomPickDao.findList(cond, null, pageIndex, pageSize);
            // 遍历查询结果
            while (materialBomPickItr.hasNext()) {
                // 获取当前查询结果的Document对象
                Document materialBomPickDoc = materialBomPickItr.next();
                // 将Document对象转换为VtuzxMap对象
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                // 向VtuzxMap对象中添加id属性
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                // 向VtuzxMap对象中添加createTime属性，并格式化日期
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                // 将VtuzxMap对象添加到List中
                pickList.add(materialBomPickMap);
            }
            // 返回一个VtuzxMap对象，包含两个键值对，一个是IVtuzxConst.Key_total，值为materialBomPickCount，另一个是IVtuzxConst.Key_data，值为pickList
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        // 创建一个空的字符串列表，用于存储billNo
        List<String> pickBillNoList = new ArrayList<>();
        // 创建一个查询条件，查询batchNo以BN开头的文档
        Criteria detailCriteria = Criteria.where("batchNo").regex("^BN");
        // 根据查询条件从数据库中获取文档列表
        Iterator<Document> detailItr = materialBomPickDetailDao.findList(detailCriteria, null, 0, 0);
        // 遍历文档列表
        while (detailItr.hasNext()) {
            // 获取下一个文档
            Document detailDoc = detailItr.next();
            // 从文档中获取billNo
            String pickBillNo = VtuzxUtil.getString(detailDoc, "billNo");
            // 如果pickBillNoList中不包含该billNo，则将其添加到pickBillNoList中
            if (!pickBillNoList.contains(pickBillNo)) {
                pickBillNoList.add(pickBillNo);
            }
        }
        // 如果pickBillNoList为空，则返回一个包含Key_total和Key_data的VtuzxMap，Key_total的值为0，Key_data的值为一个空的ArrayList
        if (pickBillNoList.isEmpty()) {
            return new VtuzxMap(IVtuzxConst.Key_total, 0).append(IVtuzxConst.Key_data, new ArrayList<>());
        }
        // 将pickBillNoList中的元素添加到cond的billNo字段中
        cond.and("billNo").in(pickBillNoList);
        //根据条件查询物料领用记录，按照创建时间降序排列，分页查询
        VtuzxPage page = materialBomPickDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        // 遍历文档，将文档中的数据转换为VtuzxMap对象，并存入dataList中
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                // 获取文档中的id，并转换为字符串
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                // 获取文档中的billNo，并转换为字符串
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                // 获取文档中的createUserName，并转换为字符串
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                // 获取文档中的_createUserId，并转换为对象
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                // 获取文档中的boxCount，并转换为整数
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                // 获取文档中的count，并转换为浮点数
                .append("status", VtuzxUtil.getString(doc, "status"))
                // 获取文档中的status，并转换为字符串
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                // 获取文档中的taskBillNo，并转换为字符串
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                // 获取文档中的produceHouse，并转换为字符串
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                // 获取文档中的stockNo，并转换为字符串
                .append("actualCount", String.format("%.2f", VtuzxUtil.getDouble(doc, "actualCount")))//实际重量
                // 获取文档中的actualCount，并转换为浮点数，并保留两位小数
                .append("discrepancy", String.format("%.2f", VtuzxUtil.getDouble(doc, "count") - VtuzxUtil.getDouble(doc, "actualCount")))
                // 获取文档中的count和actualCount，并计算差值，保留两位小数
                .append("isPrint", VtuzxUtil.getString(doc, "isPrint"))
                // 获取文档中的isPrint，并转换为字符串
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        //将查询结果封装为VtuzxMap对象，返回
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomPickBillDetail(ObjectId userId, String billNo) {
        Document materialBomPickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String scllBillNo = VtuzxUtil.getString(materialBomPickDoc, "billNo");
        String taskBillNo = VtuzxUtil.getString(materialBomPickDoc, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(materialBomPickDoc, "produceHouse");
        String createUserName = VtuzxUtil.getString(materialBomPickDoc, "createUserName");
        String taskUserName = VtuzxUtil.getString(materialBomPickDoc, "taskUserName");
        double actualCount = VtuzxUtil.getDouble(materialBomPickDoc, "actualCount");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickDoc, "createTime"));
        double count = VtuzxUtil.getDouble(materialBomPickDoc, "count");
        int boxCount = VtuzxUtil.getInt(materialBomPickDoc, "boxCount");
        //去任务表查询任务创建时间
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        Date taskTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        //把date转换成localdateTime获取当天开始时间和结束时间
        Instant instant = taskTime.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String prdRTskBillNo = VtuzxUtil.getString(map, "billNo");
            if (taskBillNo.equals(prdRTskBillNo)) {
                break;
            }
        }
        //领料单添加任务序号
        String taskCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime"));//任务创建时间
        VtuzxMap header = new VtuzxMap("billNo", scllBillNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("taskUserName", taskUserName)
                .append("createTime", createTime)
                .append("produceHouse", produceHouse)
                .append("count", String.format("%.2f", count))
                .append("taskCreateTime", taskCreateTime)
                .append("actualCount", actualCount)
                .append("orderNum", orderNum)//任务编号
                .append("boxCount", boxCount);
        //给领料单增加任务编号
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomPickDetailItr.hasNext()) {
            Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
            VtuzxMap materialBomPickDetailMap = new VtuzxMap(materialBomPickDetailDoc);
            String materialNo = VtuzxUtil.getString(materialBomPickDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(materialBomPickDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(materialBomPickDetailMap, "_createUserId");
            materialBomPickDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(materialBomPickDetailMap);
        }
        //处理数字保留两位小数
        for (VtuzxMap map : dataList) {
            double number = VtuzxUtil.getDouble(map, "count");
            map.replace("count", String.format("%.2f", number));
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    // 根据用户ID和单据号获取物料BOM领料单详情
    public VtuzxMap getMaterialBomPickBillDetailBn(ObjectId userId, String billNo) {
        // 根据billNo查询materialBomPickDao
        Document materialBomPickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        // 获取materialBomPickDoc中的billNo
        String scllBillNo = VtuzxUtil.getString(materialBomPickDoc, "billNo");
        // 获取materialBomPickDoc中的taskBillNo
        String taskBillNo = VtuzxUtil.getString(materialBomPickDoc, "taskBillNo");
        // 获取materialBomPickDoc中的produceHouse
        String produceHouse = VtuzxUtil.getString(materialBomPickDoc, "produceHouse");
        // 获取materialBomPickDoc中的createUserName
        String createUserName = VtuzxUtil.getString(materialBomPickDoc, "createUserName");
        // 获取materialBomPickDoc中的taskUserName
        String taskUserName = VtuzxUtil.getString(materialBomPickDoc, "taskUserName");
        // 获取materialBomPickDoc中的actualCount
        double actualCount = VtuzxUtil.getDouble(materialBomPickDoc, "actualCount");
        // 获取materialBomPickDoc中的createTime并格式化为yyyy-MM-dd HH:mm:ss.SSS
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickDoc, "createTime"));
        // 获取materialBomPickDoc中的count
        double count = VtuzxUtil.getDouble(materialBomPickDoc, "count");
        // 获取materialBomPickDoc中的boxCount
        int boxCount = VtuzxUtil.getInt(materialBomPickDoc, "boxCount");
        //去任务表查询任务创建时间
        // 根据任务单号查询任务单文档
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        // 从任务单文档中获取创建时间
        Date taskTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        //把date转换成localdateTime获取当天开始时间和结束时间
        // 将taskTime转换为Instant对象
        Instant instant = taskTime.toInstant();
        // 获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();
        // 将Instant对象转换为LocalDateTime对象
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        // 将LocalDateTime对象的时间部分设置为当天的开始时间
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        // 将LocalDateTime对象的时间部分设置为当天的结束时间
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String prdRTskBillNo = VtuzxUtil.getString(map, "billNo");
            if (taskBillNo.equals(prdRTskBillNo)) {
                break;
            }
        }
        //领料单添加任务序号
        String taskCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime"));//任务创建时间
        // 创建一个VtuzxMap对象，并添加以下键值对
        VtuzxMap header = new VtuzxMap("billNo", scllBillNo)
                // 账单编号
                .append("taskBillNo", taskBillNo)
                // 任务账单编号
                .append("createUserName", createUserName)
                // 创建用户名
                .append("taskUserName", taskUserName)
                // 任务用户名
                .append("createTime", createTime)
                // 创建时间
                .append("produceHouse", produceHouse)
                // 产房
                .append("count", String.format("%.2f", count))
                // 数量，保留两位小数
                .append("taskCreateTime", taskCreateTime)
                // 任务创建时间
                .append("actualCount", actualCount)
                // 实际数量
                .append("orderNum", orderNum)
                // 订单编号
                .append("boxCount", boxCount);
        //给领料单增加任务编号
        List<VtuzxMap> dataList = new ArrayList<>();
        // 只查询批次号以BN开头的物料
        Criteria detailCriteria = Criteria.where("billNo").is(billNo).and("batchNo").regex("^BN");
        // 创建一个迭代器，用于遍历materialBomPickDetailDao中满足detailCriteria条件的Document对象
        Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(detailCriteria, null, 0, 0);
        // 遍历物料BOM领料明细
        while (materialBomPickDetailItr.hasNext()) {
            // 获取物料BOM领料明细文档
            Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
            // 将文档转换为Map
            VtuzxMap materialBomPickDetailMap = new VtuzxMap(materialBomPickDetailDoc);
            // 获取物料编号
            String materialNo = VtuzxUtil.getString(materialBomPickDetailMap, "materialNo");
            // 根据物料编号查询物料文档
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            // 获取物料的基本单位
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            // 移除文档中的_id字段
            String _id = VtuzxUtil.removeString(materialBomPickDetailMap, IVtuzxConst.Key__id);
            // 移除文档中的_createUserId字段
            // 获取materialBomPickDetailMap中"_createUserId"字段的值，并赋值给_createUserId变量
            String _createUserId = VtuzxUtil.removeString(materialBomPickDetailMap, "_createUserId");
            // 向materialBomPickDetailMap中添加"_id"字段，值为_id
            materialBomPickDetailMap.append("_id", _id)
                    // 向materialBomPickDetailMap中添加"_createUserId"字段，值为_createUserId
                    .append("_createUserId", _createUserId)
                    // 向materialBomPickDetailMap中添加"unit"字段，值为fBaseUnitIdFName
                    .append("unit", fBaseUnitIdFName);
            // 将materialBomPickDetailMap添加到dataList中
            dataList.add(materialBomPickDetailMap);
        }
        //处理数字保留两位小数
        // 遍历dataList中的每一个VtuzxMap对象
        for (VtuzxMap map : dataList) {
            // 获取VtuzxMap对象中键为"count"的值，并转换为double类型
            double number = VtuzxUtil.getDouble(map, "count");
            // 将VtuzxMap对象中键为"count"的值替换为保留两位小数的字符串
            map.replace("count", String.format("%.2f", number));
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomPickBillDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomPickDetailBoxItr = materialBomPickDetailBoxDao.findList(cond, null, 0, 0);
        while (materialBomPickDetailBoxItr.hasNext()) {
            Document materialBomPickDetailBoxDoc = materialBomPickDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomPickDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap addMaterialBomSupplementBox(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String billNo = VtuzxUtil.getString(param, "billNo");
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");

        List<VtuzxMap> boxNoDateList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        for (Map<String, Object> box : boxList) {
            boxNoList.add(VtuzxUtil.getString(box, "boxNo"));
        }
        Iterator<Document> scanBoxDocItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("boxNo").in(boxNoList).and("isTemp").is(true), null, 0, 0);
        while (scanBoxDocItr.hasNext()) {
            Document scanDoc = scanBoxDocItr.next();
            String boxNo = VtuzxUtil.getString(scanDoc, "boxNo");
            String createUserName = VtuzxUtil.getString(scanDoc, "createUserName");
            boxNoDateList.add(new VtuzxMap(boxNo, createUserName));
        }
        if (boxNoDateList.size() != 0) {
            throw new VtuzxException("托盘中箱号已添加，请删除后重新扫描!【" + boxNoDateList.toString() + "】");
        }

        for (Map<String, Object> data : boxList) {
            String stockNo = VtuzxUtil.getString(data, "stockNo");
            String locationNo = VtuzxUtil.getString(data, "locationNo");
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            String traceBack = VtuzxUtil.getString(data, "traceBack");
            boolean isZS = VtuzxUtil.getBoolean(data, "isZS");
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
            String unit = VtuzxUtil.getString(data, "unit");
            double count = VtuzxUtil.getDouble(data, "count");
            int exp = VtuzxUtil.getInt(data, "exp");
            String produceDate = VtuzxUtil.getString(data, "produceDate");
            String rfid = VtuzxUtil.getString(data, "rfid");
            Criteria cond = new Criteria("boxNo").is(boxNo).and("isTemp").is(true);
            if (isZS) {
                cond.and("traceBack").is(traceBack);
            }
            Document boxMap = materialBomSupplementDetailBoxDao.findOne(cond);
            if (!VtuzxUtil.isEmpty(boxMap)) {
                String createUserName = VtuzxUtil.getString(boxMap, "createUserName");
                throw new VtuzxException("箱号已存在，请勿重复添加！【扫码人员：" + createUserName + "】");
            }

            Criteria detailCond = Criteria.where("stockNo").is(stockNo);
            detailCond.and("materialNo").is(materialNo);
            detailCond.and("batchNo").is(batchNo);
            if (!VtuzxUtil.isEmpty(billNo)) {
                detailCond.and("status").is("save");
            } else {
                detailCond.and("isTemp").is(true);
            }
            Document detail = materialBomSupplementDetailDao.findOne(detailCond);
            Document updateVal = new Document();

            if (detail == null) {
                if (!VtuzxUtil.isEmpty(billNo)) {
                    updateVal.append("status", "save");
                    updateVal.append("billNo", billNo);
                } else {
                    updateVal.append("isTemp", true);
                }
                updateVal.append("stockNo", stockNo);
                updateVal.append("locationNo", locationNo);
                updateVal.append("materialNo", materialNo);
                updateVal.append("materialName", materialName);
                updateVal.append("materialSpec", materialSpec);
                updateVal.append("batchNo", batchNo);
                updateVal.append("unit", unit);
                updateVal.append("_createUserId", userId);
                updateVal.append("createUserName", userName);
                updateVal.append("boxCount", 1);
                if (isZS) {
                    updateVal.append("count", 1);
                } else {
                    updateVal.append("count", count);
                }
                updateVal.append("produceDate", produceDate);
                updateVal.append("exp", exp);
                updateVal.append("taskBillNo", taskBillNo);
                updateVal.append("materialBomBillNo", materialBomBillNo);
            } else {
                if (isZS) {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", 1));
                } else {
                    updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
                }
            }
            ObjectId _detailId;
            if (detail == null) {
                _detailId = materialBomSupplementDetailDao.insertOne(updateVal);
            } else {
                _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
                materialBomSupplementDetailDao.updateByIdRedirect(_detailId, updateVal);
            }

            Document detailBox = new Document();
            if (!VtuzxUtil.isEmpty(billNo)) {
                detailBox.append("status", "save");
                detailBox.append("billNo", billNo);
            } else {
                detailBox.append("isTemp", true);
            }
            detailBox.append("_detailId", _detailId);
            detailBox.append("materialNo", materialNo);
            detailBox.append("materialName", materialName);
            detailBox.append("materialSpec", materialSpec);
            detailBox.append("boxNo", boxNo);
            if (isZS) {
                detailBox.append("traceBack", traceBack);
                detailBox.append("isZS", true);
                detailBox.append("count", 1);
            } else {
                detailBox.append("count", count);
            }
            detailBox.append("batchNo", batchNo);
            detailBox.append("_createUserId", userId);
            detailBox.append("createUserName", userName);
            detailBox.append("stockNo", stockNo);
            detailBox.append("locationNo", locationNo);
            detailBox.append("unit", unit);
            detailBox.append("rfid", rfid);
            detailBox.append("materialBomBillNo", materialBomBillNo);
            detailBox.append("taskBillNo", taskBillNo);
            materialBomSupplementDetailBoxDao.insertOne(detailBox);
            if (!VtuzxUtil.isEmpty(billNo)) {
                materialBomSupplementDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("boxCount", 1).append("count", count)));
            }
        }

        return null;
    }

    @Override
    public VtuzxMap createMaterialBomSupplementBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String billNo = IXqcConst.createBillNo(BillType.SCBL);
        double actualCount = VtuzxUtil.getDouble(param, "actualCount");//实际补料

        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String taskUserName = "";
        ObjectId taskUserId = null;
        if (prdTaskDoc != null) {
            taskUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
            taskUserId = VtuzxUtil.getObject(prdTaskDoc, "_createUserId");
        }

        Criteria opCond = new Criteria();
        opCond.and("isTemp").is(true).and("_createUserId").is(userId).and("stockNo").is(stockNo);

        double sumCount = 0d;
        int sumBoxCount = 0;
        Iterator<Document> pickBoxItr = materialBomSupplementDetailBoxDao.findList(opCond, null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBox = pickBoxItr.next();
            double count = VtuzxUtil.getDouble(pickBox, "count");
            sumBoxCount++;
            sumCount += count;
        }

        materialBomSupplementDao.insertBill(userId, userName,
                new Document("billNo", billNo)
                        .append("taskBillNo", taskBillNo)
                        .append("stockNo", stockNo)
                        .append("materialBomBillNo", materialBomBillNo)
                        .append("status", BillStatus.Save.toString())
                        .append("boxCount", sumBoxCount)
                        .append("count", sumCount)
                        .append("produceHouse", produceHouse)
                        .append("taskUserName", taskUserName)
                        .append("taskUserId", taskUserId)
                        .append("actualCount", actualCount)
                        .append("isPrint", "unseal"));//是否打印

        try {
            Document detailUpdateVal = new Document("$set", new Document("billNo", billNo).append("status", "save"));
            detailUpdateVal.append("$unset", new Document("isTemp", 1));
            materialBomSupplementDetailDao.updateManyRedirect(opCond, detailUpdateVal);
            materialBomSupplementDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
        } catch (Exception e) {

            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            materialBomSupplementDao.deleteOne(rollbackCond);
            materialBomSupplementDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            materialBomSupplementDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            throw e;
        }

        return new VtuzxMap("billNo", billNo);
    }

    @Override
    public void auditMaterialBomSupplementBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        List<String> boxNoList = new ArrayList<>();
        List<VtuzxMap> bcBoxList = new ArrayList<>();
        List<Document> zsBoxList = new ArrayList<>();
        Iterator<Document> pickBoxItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBox = pickBoxItr.next();
            String boxNo = VtuzxUtil.getString(pickBox, "boxNo");
            boolean isZS = VtuzxUtil.getBoolean(pickBox, "isZS");
            String traceBack = VtuzxUtil.getString(pickBox, "traceBack");
            String boxStockNo = VtuzxUtil.getString(pickBox, "stockNo");
            if (!boxStockNo.equals(stockNo)) {
                throw new VtuzxException("仓库不对，请重新选择");
            }
            String locationNo = VtuzxUtil.getString(pickBox, "locationNo");
            double count = VtuzxUtil.getDouble(pickBox, "count");
            String[] boxValues = boxNo.split("\\|\\;");
            if (boxValues.length == 3) {
                // 已入库包材长度为3
                bcBoxList.add(new VtuzxMap("boxNo", boxNo)
                        .append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue())
                        .append("locationNo", locationNo));
            } else {
                if (isZS) {
                    zsBoxList.add(new Document("traceBack", traceBack).append("boxNo", VtuzxUtil.getString(pickBox, "boxNo")));
                } else {
                    boxNoList.add(boxNo);
                }
            }
        }
        //判断一下箱号是否出库,存在创建后过一段时间在审核的情况,在审核之前有可能已经出库了
//        Iterator<Document> detailItr = inventoryDetailDao.findList(Criteria.where("boxNo").in(boxNoList),null,0,0);
//        while (detailItr.hasNext()){
//            Document detailDoc = detailItr.next();
//            String status = VtuzxUtil.getString(detailDoc,"status");
//            String boxNo = VtuzxUtil.getString(detailDoc,"boxNo");
//            if ("out".equals(status)){
//                throw new VtuzxException(String.format("箱号:%s,已经出库",boxNo));
//            }
//        }
        //出库
        inventoryService.reduceInventory(userId, userName, BillEvent.Audit, BillType.SCBL, stockNo, billNo, boxNoList, bcBoxList, zsBoxList);


        materialBomSupplementDao.updateOne(Criteria.where("billNo").is(billNo), new Document("status", "audit"));
        try {
            Document detailUpdateVal = new Document("$unset", new Document("status", 1));
            materialBomSupplementDetailDao.updateManyRedirect(Criteria.where("billNo").is(billNo).and("status").is("save"), detailUpdateVal);
            materialBomSupplementDetailBoxDao.updateManyRedirect(Criteria.where("billNo").is(billNo).and("status").is("save"), detailUpdateVal);
//            try {
//                syncKingdeeOrderService.syncPrdReplenishment(userId, userName, billNo, "pda");
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
        } catch (Exception e) {
            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            materialBomSupplementDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            materialBomSupplementDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("status", "save")));
            throw e;
        }

    }

    @Override
    public VtuzxMap getUserMaterialBomSupplementMaterial(ObjectId userId, String stockNo, String billNo) {
        List<VtuzxMap> materialBomSupplementDetailList = new ArrayList<>();
        Document header = new Document();
        Criteria cond = new Criteria();
        if (VtuzxUtil.isEmpty(billNo)) {
            cond.and("_createUserId").is(userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        } else {
            cond.and("billNo").is(billNo);
            header = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
        }
        Iterator<Document> materialBomSupplementDetailItr = materialBomSupplementDetailDao.findList(cond, null, 0, 0);
        while (materialBomSupplementDetailItr.hasNext()) {
            Document materialBomSupplementDetailDoc = materialBomSupplementDetailItr.next();
            VtuzxMap materialBomSupplementDetailMap = new VtuzxMap(materialBomSupplementDetailDoc);
            String id = VtuzxUtil.removeString(materialBomSupplementDetailMap, IVtuzxConst.Key__id);
            String createUserId = VtuzxUtil.removeString(materialBomSupplementDetailMap, "_createUserId");
            materialBomSupplementDetailMap.append("id", id).append("createUserId", createUserId);
            materialBomSupplementDetailList.add(materialBomSupplementDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomSupplementDetailList).append("header", header);
    }

    @Override
    public VtuzxMap getUserMaterialBomSupplementMaterialBox(ObjectId userId, String detailId) {
        List<VtuzxMap> materialBomSupplementDetailBoxList = new ArrayList<>();
        Iterator<Document> materialBomSupplementDetailBoxItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("_createUserId").is(userId).and("_detailId").is(new ObjectId(detailId)), null, 0, 0);
        while (materialBomSupplementDetailBoxItr.hasNext()) {
            Document materialBomSupplementDetailBoxDoc = materialBomSupplementDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomSupplementDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            materialBomSupplementDetailBoxList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomSupplementDetailBoxList);
    }

    @Override
    public void deleteUserMaterialBomSupplementMaterial(ObjectId userId, String id) {
        Document detailDoc = materialBomSupplementDetailDao.findById(id);
        String billNo = VtuzxUtil.getString(detailDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            int boxCount = VtuzxUtil.getInt(detailDoc, "boxCount");
            materialBomSupplementDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -boxCount)));
            Document suppleDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
            if (VtuzxUtil.getDouble(suppleDoc, "count") <= 0) {
                materialBomSupplementDao.deleteOne(Criteria.where("billNo").is(billNo));
            }
        }
        materialBomSupplementDetailDao.deleteById(FastUtil.convertId(id));
        materialBomSupplementDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserMaterialBomSupplementMaterialBox(ObjectId userId, String id) {
        Document materialBomSupplementDetailBoxDoc = materialBomSupplementDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(materialBomSupplementDetailBoxDoc, "_detailId");
        String billNo = VtuzxUtil.getString(materialBomSupplementDetailBoxDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(materialBomSupplementDetailBoxDoc, "count");
            materialBomSupplementDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -1)));

        }
        materialBomSupplementDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> materialBomSupplementDetailBoxItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (materialBomSupplementDetailBoxItr.hasNext()) {
            Document doc = materialBomSupplementDetailBoxItr.next();
            double materialBomSupplementDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = materialBomSupplementDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0 && total == 0) {
            materialBomSupplementDetailDao.deleteById(_detailId);
        } else {
            materialBomSupplementDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
    }

    @Override
    public VtuzxMap getMaterialBomSupplementBill(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        String taskBillNo = VtuzxUtil.getObject(param, "taskBillNo");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        Criteria cond = new Criteria();
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(materialBomBillNo)) {
            cond.and("materialBomBillNo").regex(materialBomBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").regex(isPrint);
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = materialBomSupplementDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomSupplementDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomSupplementDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomSupplementDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomSupplementDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = materialBomSupplementDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("actualCount", String.format("%.2f", VtuzxUtil.getDouble(doc, "actualCount")))//实际重量
                .append("discrepancy", String.format("%.2f", VtuzxUtil.getDouble(doc, "count") - VtuzxUtil.getDouble(doc, "actualCount")))
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                .append("isPrint", VtuzxUtil.getString(doc, "isPrint"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    // 根据用户ID、参数、页码和每页数量获取物料BOM补充单据
    public VtuzxMap getMaterialBomSupplementBillBn(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        // 从参数中获取单据号
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 从参数中获取物料BOM单据号
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        // 从参数中获取生产车间
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        // 从参数中获取物料号
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        // 从参数中获取箱号
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        // 从参数中获取批次号
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        // 从参数中获取创建人姓名
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        // 从参数中获取创建时间
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        // 从参数中获取任务单据号
        String taskBillNo = VtuzxUtil.getObject(param, "taskBillNo");
        // 从参数中获取是否打印
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        // 创建一个Criteria对象
        Criteria cond = new Criteria();
        //数量等于零的不显示
        cond.and("count").ne(0);
        // 判断materialBomBillNo是否为空，如果不为空，则添加模糊查询条件
        if (!VtuzxUtil.isEmpty(materialBomBillNo)) {
            cond.and("materialBomBillNo").regex(materialBomBillNo);
        }
        // 判断billNo是否为空，如果不为空，则添加模糊查询条件
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        // 判断produceHouse是否为空，如果不为空，则添加模糊查询条件
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        // 判断createUserName是否为空
        if (!VtuzxUtil.isEmpty(createUserName)) {
            // 将createUserName按照逗号分隔，得到一个数组
            String[] splitList = createUserName.split("，");
            // 如果数组长度为1，说明只有一个createUserName
            if (splitList.length == 1) {
                // 使用正则表达式匹配createUserName
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        // 如果createTime不为空，则添加createTime条件，大于等于createTime.get(0)，小于等于createTime.get(1) 23:59:59
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        // 如果taskBillNo不为空，则添加taskBillNo条件，正则匹配taskBillNo
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        // 如果isPrint不为空，则添加isPrint条件，正则匹配isPrint
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").regex(isPrint);
        }
        // 如果materialNo或batchNo不为空，且billNo为空，则执行以下操作
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            // 创建一个String类型的List
            List<String> pickBillNoList = new ArrayList<>();
            // 创建一个Criteria对象
            Criteria pickCond = new Criteria();
            // 如果materialNo不为空，则将materialNo添加到pickCond中
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            // 如果batchNo不为空，则将batchNo添加到pickCond中
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            // 遍历物料BOM领料明细
            Iterator<Document> materialBomPickDetailItr = materialBomSupplementDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                // 获取物料BOM领料明细文档
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                // 获取领料单号
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                // 如果领料单号列表中不包含该领料单号，则将其添加到列表中
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            // 创建一个VtuzxMap的列表
            List<VtuzxMap> pickList = new ArrayList<>();
            // 获取符合条件的记录数
            long materialBomPickCount = materialBomSupplementDao.count(cond.and("billNo").in(pickBillNoList));
            // 根据条件查询记录，并按照createTime降序排列
            Iterator<Document> materialBomPickItr = materialBomSupplementDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            // 遍历查询结果
            while (materialBomPickItr.hasNext()) {
                // 获取查询结果中的每一条记录
                Document materialBomPickDoc = materialBomPickItr.next();
                // 将每一条记录转换为VtuzxMap对象
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                // 添加id字段
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                // 添加createTime字段，格式化为yyyy-MM-dd HH:mm:ss.SSS
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                // 将转换后的VtuzxMap对象添加到列表中
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        // 如果boxNo不为空，billNo为空
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            // 创建一个空的pickBillNoList
            List<String> pickBillNoList = new ArrayList<>();
            // 查找boxNo符合正则表达式的materialBomPickDetail
            Iterator<Document> materialBomPickDetailItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            // 遍历查询结果
            while (materialBomPickDetailItr.hasNext()) {
                // 获取materialBomPickDetail
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                // 获取pickBillNo
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                // 如果pickBillNoList不包含pickBillNo
                if (!pickBillNoList.contains(pickBillNo)) {
                    // 将pickBillNo添加到pickBillNoList中
                    pickBillNoList.add(pickBillNo);
                }
            }
            // 创建一个VtuzxMap类型的列表
            List<VtuzxMap> pickList = new ArrayList<>();
            // 获取符合条件的记录数
            long materialBomPickCount = materialBomSupplementDao.count(cond.and("billNo").in(pickBillNoList));
            // 查询符合条件的记录，按createTime降序排列，分页查询
            Iterator<Document> materialBomPickItr = materialBomSupplementDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            // 遍历查询结果
            while (materialBomPickItr.hasNext()) {
                // 获取每条记录
                Document materialBomPickDoc = materialBomPickItr.next();
                // 将每条记录转换为VtuzxMap类型
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                // 添加id字段
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                // 添加createTime字段，格式化为"yyyy-MM-dd HH:mm:ss.SSS"格式
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                // 将转换后的记录添加到列表中
                pickList.add(materialBomPickMap);
            }
            // 返回一个VtuzxMap类型的结果，包含总记录数和数据列表
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        // 创建一个String类型的List，用于存储BN开头的billNo
        List<String> bnBillNos = new ArrayList<>();
        // 创建一个Criteria对象，用于查询batchNo以BN开头的记录
        Criteria detailCriteria = Criteria.where("batchNo").regex("^BN");
        // 获取物料BOM补充明细列表
        Iterator<Document> detailItr = materialBomSupplementDetailDao.findList(detailCriteria, null, 0, 0);
        // 遍历列表
        while (detailItr.hasNext()) {
            // 获取当前元素
            Document doc = detailItr.next();
            // 获取当前元素的billNo字段
            String detailBillNo = VtuzxUtil.getString(doc, "billNo");
            // 如果billNo不在bnBillNos中，则添加
            if (!bnBillNos.contains(detailBillNo)) {
                bnBillNos.add(detailBillNo);
            }
        }
        // 判断bnBillNos是否为空
        if (bnBillNos.isEmpty()) {
            // 如果为空，则返回一个VtuzxMap对象，其中包含两个键值对，键为IVtuzxConst.Key_total，值为0，键为IVtuzxConst.Key_data，值为一个空的ArrayList
            return new VtuzxMap(IVtuzxConst.Key_total, 0).append(IVtuzxConst.Key_data, new ArrayList<>());
        }
        // 根据billNo字段，将bnBillNos中的值作为条件进行查询
        cond.and("billNo").in(bnBillNos);
        // 根据查询条件，按照createTime字段进行降序排序，获取分页数据
        VtuzxPage page = materialBomSupplementDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        // 将查询结果中的数据转换为VtuzxMap对象
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("actualCount", String.format("%.2f", VtuzxUtil.getDouble(doc, "actualCount")))//实际重量
                .append("discrepancy", String.format("%.2f", VtuzxUtil.getDouble(doc, "count") - VtuzxUtil.getDouble(doc, "actualCount")))
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                .append("isPrint", VtuzxUtil.getString(doc, "isPrint"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        // 返回分页结果
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomSupplementBillDetail(ObjectId userId, String billNo) {
        Document materialBomSupplementDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
        String scblBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "taskBillNo");
        String taskUserName = VtuzxUtil.getString(materialBomSupplementDoc, "taskUserName");
        String createUserName = VtuzxUtil.getString(materialBomSupplementDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomSupplementDoc, "createTime"));
        String produceHouse = VtuzxUtil.getString(materialBomSupplementDoc, "produceHouse");
        double count = VtuzxUtil.getDouble(materialBomSupplementDoc, "count");
        double actualCount = VtuzxUtil.getDouble(materialBomSupplementDoc, "actualCount");
        int boxCount = VtuzxUtil.getInt(materialBomSupplementDoc, "boxCount");
        //添加任务编号
        Date taskreateTime = null;
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        if (!VtuzxUtil.isEmpty(prdTaskDoc)) {
            taskreateTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        }

        //把date转换成localdateTime获取当天开始时间和结束时间
        Instant instant = taskreateTime.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String prdTaskBillNo = VtuzxUtil.getString(map, "billNo");
            if (taskBillNo.equals(prdTaskBillNo)) {
                break;
            }
        }
        String taskCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime"));//任务创建时间
        VtuzxMap header = new VtuzxMap("billNo", scblBillNo)
                .append("materialBomBillNo", materialBomBillNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("taskUserName", taskUserName)
                .append("createTime", createTime)
                .append("actualCount", actualCount)
                .append("produceHouse", produceHouse)
                .append("count", String.format("%.2f", count))
                .append("taskCreateTime", taskCreateTime)
                .append("orderNum", orderNum)//任务序号
                .append("boxCount", boxCount);


        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomSupplementDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomSupplementDetailItr.hasNext()) {
            Document materialBomSupplementDetailDoc = materialBomSupplementDetailItr.next();
            VtuzxMap materialBomSupplementDetailMap = new VtuzxMap(materialBomSupplementDetailDoc);
            String materialNo = VtuzxUtil.getString(materialBomSupplementDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(materialBomSupplementDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(materialBomSupplementDetailMap, "_createUserId");

            materialBomSupplementDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(materialBomSupplementDetailMap);
        }
        for (VtuzxMap data : dataList) {
            double dataCount = VtuzxUtil.getDouble(data, "count");
            data.replace("count", String.format("%.2f", dataCount));
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomSupplementBillDetailBn(ObjectId userId, String billNo) {
        Document materialBomSupplementDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
        String scblBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(materialBomSupplementDoc, "taskBillNo");
        String taskUserName = VtuzxUtil.getString(materialBomSupplementDoc, "taskUserName");
        String createUserName = VtuzxUtil.getString(materialBomSupplementDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomSupplementDoc, "createTime"));
        String produceHouse = VtuzxUtil.getString(materialBomSupplementDoc, "produceHouse");
        double count = VtuzxUtil.getDouble(materialBomSupplementDoc, "count");
        double actualCount = VtuzxUtil.getDouble(materialBomSupplementDoc, "actualCount");
        int boxCount = VtuzxUtil.getInt(materialBomSupplementDoc, "boxCount");
        //添加任务编号
        Date taskreateTime = null;
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        if (!VtuzxUtil.isEmpty(prdTaskDoc)) {
            taskreateTime = VtuzxUtil.getObject(prdTaskDoc, "createTime");
        }

        //把date转换成localdateTime获取当天开始时间和结束时间
        Instant instant = taskreateTime.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String prdTaskBillNo = VtuzxUtil.getString(map, "billNo");
            if (taskBillNo.equals(prdTaskBillNo)) {
                break;
            }
        }
        String taskCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime"));//任务创建时间
        VtuzxMap header = new VtuzxMap("billNo", scblBillNo)
                .append("materialBomBillNo", materialBomBillNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("taskUserName", taskUserName)
                .append("createTime", createTime)
                .append("actualCount", actualCount)
                .append("produceHouse", produceHouse)
                .append("count", String.format("%.2f", count))
                .append("taskCreateTime", taskCreateTime)
                .append("orderNum", orderNum)//任务序号
                .append("boxCount", boxCount);


        List<VtuzxMap> dataList = new ArrayList<>();
        //Iterator<Document> materialBomSupplementDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);

        Iterator<Document> materialBomSupplementDetailItr = materialBomSupplementDetailDao.findList(
                Criteria.where("billNo").is(billNo).and("batchNo").regex("^BN"), //增加BN批次过滤
                null, 0, 0
        );

        while (materialBomSupplementDetailItr.hasNext()) {
            Document materialBomSupplementDetailDoc = materialBomSupplementDetailItr.next();
            VtuzxMap materialBomSupplementDetailMap = new VtuzxMap(materialBomSupplementDetailDoc);
            String materialNo = VtuzxUtil.getString(materialBomSupplementDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(materialBomSupplementDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(materialBomSupplementDetailMap, "_createUserId");

            materialBomSupplementDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(materialBomSupplementDetailMap);
        }
        for (VtuzxMap data : dataList) {
            double dataCount = VtuzxUtil.getDouble(data, "count");
            data.replace("count", String.format("%.2f", dataCount));
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomSupplementBillDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomSupplementDetailBoxItr = materialBomSupplementDetailBoxDao.findList(cond, null, 0, 0);
        while (materialBomSupplementDetailBoxItr.hasNext()) {
            Document materialBomSupplementDetailBoxDoc = materialBomSupplementDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomSupplementDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getProduceReturnList(ObjectId userId, String taskBillNo) {
        List<VtuzxMap> dataList = new ArrayList<>();

        Iterator<Document> pickBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBoxDoc = pickBoxItr.next();
            VtuzxMap pickBoxMap = new VtuzxMap(pickBoxDoc);
            pickBoxMap.append("id", VtuzxUtil.removeString(pickBoxMap, "_id"));
            pickBoxMap.append("detailId", VtuzxUtil.removeString(pickBoxMap, "_detailId"));
            pickBoxMap.append("createUserId", VtuzxUtil.removeString(pickBoxMap, "_createUserId"));
            pickBoxMap.append("currentCount", VtuzxUtil.getDouble(pickBoxMap, "count"));
            Date createTime = VtuzxUtil.getObject(pickBoxMap, "createTime");
            pickBoxMap.remove("createTime");
            pickBoxMap.remove("updateTime");
            pickBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(pickBoxMap);
        }

        Iterator<Document> supplementBoxItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (supplementBoxItr.hasNext()) {
            Document supplementBoxDoc = supplementBoxItr.next();
            VtuzxMap supplementBoxMap = new VtuzxMap(supplementBoxDoc);
            supplementBoxMap.append("id", VtuzxUtil.removeString(supplementBoxMap, "_id"));
            supplementBoxMap.append("detailId", VtuzxUtil.removeString(supplementBoxMap, "_detailId"));
            supplementBoxMap.append("createUserId", VtuzxUtil.removeString(supplementBoxMap, "_createUserId"));
            supplementBoxMap.append("currentCount", VtuzxUtil.getDouble(supplementBoxMap, "count"));
            Date createTime = VtuzxUtil.getObject(supplementBoxMap, "createTime");
            supplementBoxMap.remove("createTime");
            supplementBoxMap.remove("updateTime");
            supplementBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(supplementBoxMap);
        }
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(taskBillNo)
                .and("colType").is("return"),null,0,0);

        List<Document> colList = new ArrayList<>();

        while (prdColItr.hasNext()){
            Document prdcolDetailDoc = prdColItr.next();
            colList.add(prdcolDetailDoc);
        }


        VtuzxMap colMap = new VtuzxMap();//val:物料加批号 val:退料数量
        for (Document prdColDoc : colList ){
            String colmaterialNo = VtuzxUtil.getString(prdColDoc,"materialNo");
            String colbatchNo = VtuzxUtil.getString(prdColDoc,"batchNo");
            Double returnCount = VtuzxUtil.getDouble(colMap,colmaterialNo + "_" + colbatchNo);
            Double colCount = VtuzxUtil.getDouble(prdColDoc,"count");
            colMap.put(colmaterialNo + "_" + colbatchNo,colCount + returnCount);
        }

        for (VtuzxMap data : dataList){
            String materialNo = VtuzxUtil.getString(data,"materialNo");
            String batchNo = VtuzxUtil.getString(data,"batchNo");
            double count = VtuzxUtil.getDouble(data,"count");
            double returnCount = VtuzxUtil.getDouble(colMap,materialNo + "_" + batchNo);
            if (count >= returnCount){//判断数量是否够扣
                data.append("count",count - returnCount);
                data.append("currentCount",count - returnCount);
                colMap.append(materialNo + "_" + batchNo,0);
            } else {
                data.append("count",0);
                data.append("currentCount",0);
                colMap.append(materialNo + "_" + batchNo,returnCount - count);
            }

        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getProduceReturnBox(ObjectId userId, String taskBillNo, String boxNoKey) throws VtuzxException {

        // 管理箱号
        String boxNo;
        if (boxNoKey.contains("|;")) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 6) {
                boxNo = boxNoKey;
                boxNo = boxNo.substring(boxNo.lastIndexOf("|;") + 2);
            } else {
                boxNo = boxValues[boxValues.length - 1];
            }
        } else {
            boxNo = boxNoKey;
        }

        List<VtuzxMap> dataList = new ArrayList<>();
        Criteria cond = new Criteria("taskBillNo").is(taskBillNo).and("boxNo").is(boxNo);
        Document pickBoxDoc = materialBomPickDetailBoxDao.findOne(cond);
        if (pickBoxDoc != null) {
            VtuzxMap pickBoxMap = new VtuzxMap(pickBoxDoc);
            pickBoxMap.append("id", VtuzxUtil.removeString(pickBoxMap, "_id"));
            pickBoxMap.append("detailId", VtuzxUtil.removeString(pickBoxMap, "_detailId"));
            pickBoxMap.append("createUserId", VtuzxUtil.removeString(pickBoxMap, "_createUserId"));
            Date createTime = VtuzxUtil.getObject(pickBoxMap, "createTime");
            pickBoxMap.remove("createTime");
            pickBoxMap.remove("updateTime");
            pickBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(pickBoxMap);
        }


        Document supplementBoxDoc = materialBomSupplementDetailBoxDao.findOne(cond);
        if (supplementBoxDoc != null) {
            VtuzxMap supplementBoxMap = new VtuzxMap(supplementBoxDoc);
            supplementBoxMap.append("id", VtuzxUtil.removeString(supplementBoxMap, "_id"));
            supplementBoxMap.append("detailId", VtuzxUtil.removeString(supplementBoxMap, "_detailId"));
            supplementBoxMap.append("createUserId", VtuzxUtil.removeString(supplementBoxMap, "_createUserId"));
            Date createTime = VtuzxUtil.getObject(supplementBoxMap, "createTime");
            supplementBoxMap.remove("createTime");
            supplementBoxMap.remove("updateTime");
            supplementBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(supplementBoxMap);
        }

        if (dataList.size() == 0) {
            throw new VtuzxException("箱号不存在");
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getProduceReturnRfid(ObjectId userId, String taskBillNo, List<String> rfidList) throws VtuzxException {
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> pickBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("rfid").in(rfidList), null, 0, 0);
        while (pickBoxItr.hasNext()) {
            Document pickBoxDoc = pickBoxItr.next();
            VtuzxMap pickBoxMap = new VtuzxMap(pickBoxDoc);
            pickBoxMap.append("id", VtuzxUtil.removeString(pickBoxMap, "_id"));
            pickBoxMap.append("detailId", VtuzxUtil.removeString(pickBoxMap, "_detailId"));
            pickBoxMap.append("createUserId", VtuzxUtil.removeString(pickBoxMap, "_createUserId"));
            Date createTime = VtuzxUtil.getObject(pickBoxMap, "createTime");
            pickBoxMap.remove("createTime");
            pickBoxMap.remove("updateTime");
            pickBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(pickBoxMap);
        }


        Iterator<Document> supplementBoxItr = materialBomSupplementDetailBoxDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("rfid").in(rfidList), null, 0, 0);
        while (supplementBoxItr.hasNext()) {
            Document supplementBoxDoc = supplementBoxItr.next();
            VtuzxMap supplementBoxMap = new VtuzxMap(supplementBoxDoc);
            supplementBoxMap.append("id", VtuzxUtil.removeString(supplementBoxMap, "_id"));
            supplementBoxMap.append("detailId", VtuzxUtil.removeString(supplementBoxMap, "_detailId"));
            supplementBoxMap.append("createUserId", VtuzxUtil.removeString(supplementBoxMap, "_createUserId"));
            Date createTime = VtuzxUtil.getObject(supplementBoxMap, "createTime");
            supplementBoxMap.remove("createTime");
            supplementBoxMap.remove("updateTime");
            supplementBoxMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
            dataList.add(supplementBoxMap);
        }

        if (dataList.size() == 0) {
            throw new VtuzxException("rfid不存在");
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void addMaterialBomBoxReturn(ObjectId userId, String userName, List<Map<String, Object>> dataList, String taskBillNo, String materialBomBillNo) throws VtuzxException {
        Document pickBoxDoc;
        pickBoxDoc = materialBomPickDetailBoxDao.findOne(Criteria.where("boxNo").is(VtuzxUtil.getString(dataList.get(0), "boxNo")));
        if (VtuzxUtil.isEmpty(pickBoxDoc)) {
            pickBoxDoc = materialBomSupplementDetailBoxDao.findOne(Criteria.where("boxNo").is(VtuzxUtil.getString(dataList.get(0), "boxNo")));
        }
        String pickBillNo = VtuzxUtil.getString(pickBoxDoc, "billNo");
        Document pickDoc;
        if (pickBillNo.startsWith("SCBL")) {
            pickDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(pickBillNo));
        } else {
            pickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(pickBillNo));
        }
        String status = VtuzxUtil.getString(pickDoc, "status");
        if ("save".equals(status)) {
            throw new VtuzxException(String.format("订单[%s]未审核，不允许退料", pickBillNo));
        }

        for (Map<String, Object> data : dataList) {
            String stockNo = VtuzxUtil.getString(data, "stockNo");
            String locationNo = VtuzxUtil.getString(data, "locationNo");
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
            String unit = VtuzxUtil.getString(data, "unit");
            double count = VtuzxUtil.getDouble(data, "count");
            int exp = VtuzxUtil.getInt(data, "exp");
            String produceDate = VtuzxUtil.getString(data, "produceDate");
            String rfid = VtuzxUtil.getString(data, "rfid");
            String billNo = VtuzxUtil.getString(data, "billNo");
            Document boxMap = materialBomReturnDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo).and("isTemp").is(true));
            if (!VtuzxUtil.isEmpty(boxMap)) {
                String createUserName = VtuzxUtil.getString(boxMap, "createUserName");
                throw new VtuzxException("箱号已存在，请勿重复添加！【扫码人员：" + createUserName + "】");
            }

            Criteria detailCond = Criteria.where("stockNo").is(stockNo);
            detailCond.and("materialNo").is(materialNo);
            detailCond.and("isTemp").is(true);
            detailCond.and("batchNo").is(batchNo);
            detailCond.and("taskBillNo").is(taskBillNo);
            Document detail = materialBomReturnDetailDao.findOne(detailCond);
            Document updateVal = new Document();

            if (detail == null) {
                updateVal.append("isTemp", true);
                updateVal.append("stockNo", stockNo);
                updateVal.append("locationNo", locationNo);
                updateVal.append("materialNo", materialNo);
                updateVal.append("materialName", materialName);
                updateVal.append("materialSpec", materialSpec);
                updateVal.append("batchNo", batchNo);
                updateVal.append("unit", unit);
                updateVal.append("_createUserId", userId);
                updateVal.append("createUserName", userName);
                updateVal.append("boxCount", 1);
                updateVal.append("count", count);
                updateVal.append("produceDate", produceDate);
                updateVal.append("exp", exp);
                updateVal.append("materialBomBillNo", materialBomBillNo);
                updateVal.append("taskBillNo", taskBillNo);
            } else {
                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
            }
            ObjectId _detailId;
            if (detail == null) {
                _detailId = materialBomReturnDetailDao.insertOne(updateVal);
            } else {
                _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
                materialBomReturnDetailDao.updateByIdRedirect(_detailId, updateVal);
            }

            Document detailBox = new Document();
            detailBox.append("isTemp", true);
            detailBox.append("_detailId", _detailId);
            detailBox.append("materialNo", materialNo);
            detailBox.append("materialName", materialName);
            detailBox.append("materialSpec", materialSpec);
            detailBox.append("boxNo", boxNo);
            detailBox.append("count", count);
            detailBox.append("batchNo", batchNo);
            detailBox.append("_createUserId", userId);
            detailBox.append("createUserName", userName);
            detailBox.append("stockNo", stockNo);
            detailBox.append("locationNo", locationNo);
            detailBox.append("unit", unit);
            detailBox.append("rfid", rfid);
            detailBox.append("taskBillNo", taskBillNo);
            detailBox.append("materialBomBillNo", materialBomBillNo);
            materialBomReturnDetailBoxDao.insertOne(detailBox);
        }
    }

    @Override
    public void createMaterialBomReturnBill(ObjectId userId, String userName, Map<String, Object> param) throws InterruptedException {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String billNo = IXqcConst.createBillNo(BillType.SCTL);

        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String taskUserName = "";
        ObjectId taskUserId = null;
        if (prdTaskDoc != null) {
            taskUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
            taskUserId = VtuzxUtil.getObject(prdTaskDoc, "_createUserId");
        }


        Criteria opCond = new Criteria();
        opCond.and("isTemp").is(true).and("_createUserId").is(userId);

        List<String> boxNoList = new ArrayList<>();
        List<Document> dataList = new ArrayList<>();
        double sumCount = 0d;
        int sumBoxCount = 0;
        Iterator<Document> returnBoxItr = materialBomReturnDetailBoxDao.findList(opCond, null, 0, 0);
        while (returnBoxItr.hasNext()) {
            Document returnBox = returnBoxItr.next();
            double count = VtuzxUtil.getDouble(returnBox, "count");
            String boxNo = VtuzxUtil.getString(returnBox, "boxNo");
            sumBoxCount++;
            sumCount += count;
            boxNoList.add(boxNo);
            dataList.add(returnBox);
        }

        List<Document> inventoryDetailList = new ArrayList<>();
        Iterator<Document> inventoryDetailItr = inventoryDetailDao.findList(Criteria.where("boxNo").in(boxNoList).and("status").is("out"), new Document("createTime", -1), 0, 0);
        while (inventoryDetailItr.hasNext()) {
            Document inventoryDetailDoc = inventoryDetailItr.next();
            inventoryDetailList.add(inventoryDetailDoc);
        }

        VtuzxMap boxMap = new VtuzxMap();//key:物料加批次  value:箱号信息集合
        for (Document data : dataList) {
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
            double count = VtuzxUtil.getDouble(data, "count");


            VtuzxMap dataMap = new VtuzxMap(data);
            dataMap.remove("_id");
            dataMap.remove("_detailId");
            dataMap.remove("createTime");
            dataMap.remove("updateTime");
            dataMap.remove("_createUserId");
            dataMap.remove("createUserName");
            dataMap.remove("count");
            dataMap.remove("boxNo");
            dataMap.remove("isTemp");
            for (Document inDetail : inventoryDetailList) {
                List<VtuzxMap> boxList = new ArrayList<>();
                String inBoxNo = "";
                double inCount = VtuzxUtil.getDouble(inDetail, "count");
                String getBoxNo = VtuzxUtil.getString(inDetail, "boxNo");
                if (boxNo.equals(getBoxNo)) {
                    if (inCount == count) {
                        inBoxNo = VtuzxUtil.getString(inDetail, "boxNo");
                    } else {
                        inBoxNo = "A02" + new Date().getTime();
                        Thread.sleep(10);
                    }
                    dataMap.append("boxNo", inBoxNo).append("count", count);
                    List<VtuzxMap> saveBoxList = VtuzxUtil.getObject(boxMap, materialNo + "_" + batchNo);
                    if (saveBoxList == null) {
                        boxList.add(dataMap);
                        boxMap.append(materialNo + "_" + batchNo, boxList);
                    } else {
                        saveBoxList.add(dataMap);
                    }
                    break;
                }
            }

        }

        boxMap.forEach((k, v) -> {
            String prdHouseBillNo = IXqcConst.createBillNo2(BillType.CJSH);
            List<Document> documentList = new ArrayList<>();
            List<VtuzxMap> boxList = (List<VtuzxMap>) v;
            VtuzxMap map = boxList.get(0);
            String materialNo = VtuzxUtil.getString(map, "materialNo");
            String materialSpec = VtuzxUtil.getString(map, "materialSpec");
            String materialName = VtuzxUtil.getString(map, "materialName");
            String headerComment = VtuzxUtil.getString(map, "comment");
            String headerUnit = VtuzxUtil.getString(map, "unit");
            String batchNo = VtuzxUtil.getString(map, "batchNo");

            double totalCount = 0d;
            int totalBoxCount = 0;
            for (VtuzxMap box : boxList) {
                String comment = VtuzxUtil.getString(box, "comment");
                String boxNo = VtuzxUtil.getString(box, "boxNo");
                String unit = VtuzxUtil.getString(box, "unit");
                double count = VtuzxUtil.getDouble(box, "count");
                totalCount += count;
                totalBoxCount++;

                Document colDetailDoc = new Document("count", count)
                        .append("unit", unit)
                        .append("billNo", prdHouseBillNo)
                        .append("boxNo", boxNo)
                        .append("comment", comment)
                        .append("inStock", false)
                        .append("_insertUserId", userId)
                        .append("insertUserName", userName)
                        .append("colType", "return");
                documentList.add(colDetailDoc);
            }

            prdColDetailDao.insertMany(documentList);

            Document colDoc = new Document("materialNo", materialNo)
                    .append("materialSpec", materialSpec)
                    .append("materialName", materialName)
                    .append("taskBillNo", taskBillNo)
                    .append("batchNo", batchNo)
                    .append("remark", headerComment)
                    .append("count", totalCount)
                    .append("prdCount", totalCount)
                    .append("unit", headerUnit)
                    .append("boxCount", totalBoxCount)
                    .append("billNo", prdHouseBillNo)
                    .append("status", BillStatus.Save.toString())
                    .append("_createUserId", userId)
                    .append("createUserName", userName)
                    .append("_auditUserId", userId)
                    .append("auditUserName", userName)
                    .append("colType", "return")
                    .append("auditTime", new Date())
                    .append("isPrint", "unseal");
            prdColDao.insertOne(colDoc);
        });

        materialBomReturnDao.insertBill(userId, userName,
                new Document("billNo", billNo)
                        .append("taskBillNo", taskBillNo)
                        .append("materialBomBillNo", materialBomBillNo)
                        .append("status", BillStatus.Audit.toString())
                        .append("boxCount", sumBoxCount)
                        .append("count", sumCount)
                        .append("produceHouse", produceHouse)
                        .append("taskUserName", taskUserName)
                        .append("taskUserId", taskUserId));

        try {
            Document detailUpdateVal = new Document("$set", new Document("billNo", billNo));
            detailUpdateVal.append("$unset", new Document("isTemp", 1));
            materialBomReturnDetailDao.updateManyRedirect(opCond, detailUpdateVal);
            materialBomReturnDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
            try {
//                syncKingdeeOrderService.syncPrdReturn(userId, userName, billNo, "pda");
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
        } catch (Exception e) {
            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            materialBomReturnDao.deleteOne(rollbackCond);
            materialBomReturnDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            materialBomReturnDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            throw e;
        }

    }

    /**
     * 校验退料的数量不能大于领料或者补料的数量
     * @return
     */
    private Boolean checkReturnCount(){

        return true;
    }

    @Override
    public VtuzxMap getPrdReturnListPda(ObjectId userId, String userName, String billNo) {
        VtuzxMap returnMap = null;
        Document returnDoc = materialBomReturnDao.findOne(Criteria.where("taskBillNo").is(billNo));
        if (returnDoc != null) {
            returnMap = new VtuzxMap(returnDoc);
            returnMap.append("id", VtuzxUtil.removeString(returnMap, "_id"));
            returnMap.append("createUserId", VtuzxUtil.removeString(returnMap, "_createUserId"));
            Date createTime = VtuzxUtil.getObject(returnMap, "createTime");
            returnMap.remove("_updateUserId");
            returnMap.remove("updateUserName");
            returnMap.remove("updateTime");
            returnMap.remove("createTime");
            returnMap.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));
        }

        return returnMap;
    }

    @Override
    public VtuzxMap getUserMaterialBomReturnMaterial(ObjectId userId) {
        List<VtuzxMap> materialBomReturnDetailList = new ArrayList<>();
        Iterator<Document> materialBomReturnDetailItr = materialBomReturnDetailDao.findList(Criteria.where("_createUserId").is(userId).and("isTemp").is(true), null, 0, 0);
        while (materialBomReturnDetailItr.hasNext()) {
            Document materialBomReturnDetailDoc = materialBomReturnDetailItr.next();
            VtuzxMap materialBomReturnDetailMap = new VtuzxMap(materialBomReturnDetailDoc);
            String id = VtuzxUtil.removeString(materialBomReturnDetailMap, IVtuzxConst.Key__id);
            String createUserId = VtuzxUtil.removeString(materialBomReturnDetailMap, "_createUserId");
            materialBomReturnDetailMap.append("id", id).append("createUserId", createUserId);
            materialBomReturnDetailList.add(materialBomReturnDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomReturnDetailList);
    }

    @Override
    public VtuzxMap getUserMaterialBomReturnMaterialBox(ObjectId userId, String detailId) {
        List<VtuzxMap> materialBomReturnDetailBoxList = new ArrayList<>();
        Iterator<Document> materialBomReturnDetailBoxItr = materialBomReturnDetailBoxDao.findList(Criteria.where("_createUserId").is(userId).and("_detailId").is(new ObjectId(detailId)), null, 0, 0);
        while (materialBomReturnDetailBoxItr.hasNext()) {
            Document materialBomReturnDetailBoxDoc = materialBomReturnDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomReturnDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            materialBomReturnDetailBoxList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomReturnDetailBoxList);
    }

    @Override
    public void deleteUserMaterialBomReturnMaterial(ObjectId userId, String id) {
        materialBomReturnDetailDao.deleteById(FastUtil.convertId(id));
        materialBomReturnDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserMaterialBomReturnMaterialBox(ObjectId userId, String id) {
        Document materialBomReturnDetailBoxDoc = materialBomReturnDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(materialBomReturnDetailBoxDoc, "_detailId");
        materialBomReturnDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> materialBomReturnDetailBoxItr = materialBomReturnDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (materialBomReturnDetailBoxItr.hasNext()) {
            Document doc = materialBomReturnDetailBoxItr.next();
            double materialBomReturnDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = materialBomReturnDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0 && total == 0) {
            materialBomReturnDetailDao.deleteById(_detailId);
        } else {
            materialBomReturnDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
    }

    @Override
    public VtuzxMap getMaterialBomReturnBill(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(materialBomBillNo)) {
            cond.and("materialBomBillNo").regex(materialBomBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = materialBomReturnDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomReturnDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomReturnDao.findList(cond, null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = materialBomReturnDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomReturnDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomReturnDao.findList(cond, null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = materialBomReturnDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomReturnBillBn(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();

// 获取所有包含BN批次的退料单号
        List<String> bnBillNos = new ArrayList<>();
        Criteria detailCriteria = Criteria.where("batchNo").regex("^BN");
        Iterator<Document> detailItr = materialBomReturnDetailDao.findList(detailCriteria, null, 0, 0);
        while (detailItr.hasNext()) {
            Document doc = detailItr.next();
            String detailBillNo = VtuzxUtil.getString(doc, "billNo");
            if (!bnBillNos.contains(detailBillNo)) {
                bnBillNos.add(detailBillNo);
            }
        }

// 无匹配时直接返回空列表
        if (bnBillNos.isEmpty()) {
            return new VtuzxMap(IVtuzxConst.Key_total, 0).append(IVtuzxConst.Key_data, new ArrayList<>());
        }
        cond.and("billNo").in(bnBillNos); // 核心：只查询包含BN批次的退料单


        if (!VtuzxUtil.isEmpty(materialBomBillNo)) {
            cond.and("materialBomBillNo").regex(materialBomBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = materialBomReturnDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomReturnDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomReturnDao.findList(cond, null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = materialBomReturnDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = materialBomReturnDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = materialBomReturnDao.findList(cond, null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = materialBomReturnDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("produceHouse", VtuzxUtil.getString(doc, "produceHouse"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomReturnBillDetail(ObjectId userId, String billNo) {
        Document materialBomReturnDoc = materialBomReturnDao.findOne(Criteria.where("billNo").is(billNo));
        String scblBillNo = VtuzxUtil.getString(materialBomReturnDoc, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(materialBomReturnDoc, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(materialBomReturnDoc, "taskBillNo");
        String createUserName = VtuzxUtil.getString(materialBomReturnDoc, "createUserName");
        String taskUserName = VtuzxUtil.getString(materialBomReturnDoc, "taskUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomReturnDoc, "createTime"));
        String produceHouse = VtuzxUtil.getString(materialBomReturnDoc, "produceHouse");
        double count = VtuzxUtil.getDouble(materialBomReturnDoc, "count");
        int boxCount = VtuzxUtil.getInt(materialBomReturnDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scblBillNo)
                .append("materialBomBillNo", materialBomBillNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("taskUserName", taskUserName)
                .append("createTime", createTime)
                .append("produceHouse", produceHouse)
                .append("count", count)
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomReturnDetailItr = materialBomReturnDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomReturnDetailItr.hasNext()) {
            Document materialBomReturnDetailDoc = materialBomReturnDetailItr.next();
            VtuzxMap materialBomReturnDetailMap = new VtuzxMap(materialBomReturnDetailDoc);
            String materialNo = VtuzxUtil.getString(materialBomReturnDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(materialBomReturnDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(materialBomReturnDetailMap, "_createUserId");

            materialBomReturnDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(materialBomReturnDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomReturnBillDetailBn(ObjectId userId, String billNo) {
        Document materialBomReturnDoc = materialBomReturnDao.findOne(Criteria.where("billNo").is(billNo));
        String scblBillNo = VtuzxUtil.getString(materialBomReturnDoc, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(materialBomReturnDoc, "materialBomBillNo");
        String taskBillNo = VtuzxUtil.getString(materialBomReturnDoc, "taskBillNo");
        String createUserName = VtuzxUtil.getString(materialBomReturnDoc, "createUserName");
        String taskUserName = VtuzxUtil.getString(materialBomReturnDoc, "taskUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomReturnDoc, "createTime"));
        String produceHouse = VtuzxUtil.getString(materialBomReturnDoc, "produceHouse");
        double count = VtuzxUtil.getDouble(materialBomReturnDoc, "count");
        int boxCount = VtuzxUtil.getInt(materialBomReturnDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scblBillNo)
                .append("materialBomBillNo", materialBomBillNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("taskUserName", taskUserName)
                .append("createTime", createTime)
                .append("produceHouse", produceHouse)
                .append("count", count)
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();


        Iterator<Document> materialBomReturnDetailItr = materialBomReturnDetailDao.findList(
                Criteria.where("billNo").is(billNo).and("batchNo").regex("^BN"), // 核心修改
                null, 0, 0
        );

        //Iterator<Document> materialBomReturnDetailItr = materialBomReturnDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomReturnDetailItr.hasNext()) {
            Document materialBomReturnDetailDoc = materialBomReturnDetailItr.next();
            VtuzxMap materialBomReturnDetailMap = new VtuzxMap(materialBomReturnDetailDoc);
            String materialNo = VtuzxUtil.getString(materialBomReturnDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(materialBomReturnDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(materialBomReturnDetailMap, "_createUserId");

            materialBomReturnDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(materialBomReturnDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialBomReturnBillDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> materialBomReturnDetailBoxItr = materialBomReturnDetailBoxDao.findList(cond, null, 0, 0);
        while (materialBomReturnDetailBoxItr.hasNext()) {
            Document materialBomReturnDetailBoxDoc = materialBomReturnDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomReturnDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void savePrdTaskToPrdCol(ObjectId userId, String userName, String billNo, String supplierBatchNo, String produceDate) throws Exception {
        //从业务参数中查到配置在中台的业务参数，暂时没用到
        VtuzxMap sysParamMap = settingService.getParameters(new VtuzxMap("keys", new VtuzxArrayList<>("traceabilityCodeUrl")));
        VtuzxMap traceabilityCodeUrlMap = VtuzxUtil.getObject(sysParamMap, "traceabilityCodeUrl");
        if (traceabilityCodeUrlMap == null) {
            throw new VtuzxException(IXqcConst.Msg_E_system);
        }

        Criteria cond = Criteria.where("billNo").is(billNo);
        Document prdTaskDoc = prdTaskDao.findOne(cond);
        String type = VtuzxUtil.getString(prdTaskDoc, "type");
        String colMaterialNo = VtuzxUtil.getString(prdTaskDoc, "materialNo");


        List<Document> colDetailList = new ArrayList<>(); //全部数据
        List<Document> colMaterialList = new ArrayList<>(); //要留下的数据
        Iterator<Document> colDetailItr = prdColDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("_insertUserId").is(userId).and("isTemp").is(true), null, 0, 0);
        while (colDetailItr.hasNext()) {
            Document colDetailDoc = colDetailItr.next();
            double count = VtuzxUtil.getDouble(colDetailDoc, "count");
            if (count > 0) {
                colMaterialList.add(colDetailDoc);
            }
            colDetailList.add(colDetailDoc);
        }

        //分选收货的时候 校验成品是否是下单时的子项物料的对应父项物料
        if ("sorting".equals(type)) {
            Document prdTaskDetailDoc = prdTaskDetailDao.findOne(cond);
            String taskMaterialNo = VtuzxUtil.getString(prdTaskDetailDoc, "materialNo");//任务生产的物料编码
            VtuzxMap bomMap = new VtuzxMap(); //key:父项物料 val:子项物料
            Iterator<Document> bomItr = bomDao.findList(Criteria.where("childList.childMaterialNo").in(taskMaterialNo), null, 0, 0);
            while (bomItr.hasNext()) {
                Document bomDoc = bomItr.next();
                List<Document> childList = VtuzxUtil.getObject(bomDoc, "childList");
                String dadMaterialNo = VtuzxUtil.getString(bomDoc, "materialNo");
                for (Document child : childList) {
                    String childMaterialNo = VtuzxUtil.getString(child, "childMaterialNo");
                    if (childMaterialNo.equals(taskMaterialNo)) {
                        bomMap.append(dadMaterialNo, childMaterialNo);
                    }
                }
            }

            for (Document colDetail : colMaterialList) {
                String materialNo = VtuzxUtil.getString(colDetail, "materialNo");//车间收货的物料编码
                String dadMaterialNo = VtuzxUtil.getString(bomMap, materialNo);//车间收货的物料编码对应的子项物料编码
                if (!dadMaterialNo.equals(taskMaterialNo)) {
                    throw new VtuzxException(String.format("生产任务的物料[%s]不能生成物料[%s]", taskMaterialNo, materialNo));
                }
            }
        }

        //反写追溯码
        VtuzxMap boxNoTraceBackMap = new VtuzxMap();
        //按照批次物料整理后的数据
        VtuzxMap colMap = new VtuzxMap();
        for (Document colDetail : colDetailList) {
            ObjectId _id = VtuzxUtil.getObject(colDetail, "_id");
            String boxNo = VtuzxUtil.getString(colDetail, "boxNo");
            List<String> traceBack = VtuzxUtil.getObject(colDetail, "traceBack");
            boxNoTraceBackMap.append(boxNo, traceBack);
            String materialNo = VtuzxUtil.getString(colDetail, "materialNo");
            String batchNo = VtuzxUtil.getString(colDetail, "batchNo");
            double count = VtuzxUtil.getDouble(colDetail, "count");
            if ("product".equals(type)) { //半成品04开头有追溯码的传，没追溯不传，非04开头的传
                if (!materialNo.startsWith("04") || traceBack.size() != 0) {
                    if (count > 0) {
                        List<Document> colMapList = VtuzxUtil.getObject(colMap, materialNo + '_' + batchNo);
                        if (VtuzxUtil.isEmpty(colMapList)) {
                            List<Document> innerColMapList = new ArrayList<>();
                            innerColMapList.add(colDetail);
                            colMap.append(materialNo + '_' + batchNo, innerColMapList);
                        } else {
                            colMapList.add(colDetail);
                        }
                    }
                }
            } else { //分选无限制
                if (count > 0) {
                    List<Document> colMapList = VtuzxUtil.getObject(colMap, materialNo + '_' + batchNo);
                    if (VtuzxUtil.isEmpty(colMapList)) {
                        List<Document> innerColMapList = new ArrayList<>();
                        innerColMapList.add(colDetail);
                        colMap.append(materialNo + '_' + batchNo, innerColMapList);
                    } else {
                        colMapList.add(colDetail);
                    }
                }
            }
        }

        colMap.forEach((k, v) -> {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String prdHouseBillNo = IXqcConst.createBillNo(BillType.CJSH);
            String[] splitList = k.split("_");
            String materialNo = splitList[0];
            String batchNo = splitList[1];
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String materialName = VtuzxUtil.getString(materialDoc, "fName");
            String materialSpec = VtuzxUtil.getString(materialDoc, "fSpecification");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            List<Document> dataList = (List<Document>) v;
            double sumCount = 0d;
            int sumBoxCount = 0;
            //反写分录单号
            List<ObjectId> ids = new ArrayList<>();
            for (Document data : dataList) {
                ObjectId _id = VtuzxUtil.getObject(data, "_id");
                ids.add(_id);
                double count = VtuzxUtil.getDouble(data, "count");
                sumCount = sumCount + count;
                sumBoxCount++;
            }

            //分选不传生产日期
            if ("sorting".equals(type)) {
                Document colDoc = new Document("materialNo", materialNo)
                        .append("materialSpec", materialSpec)
                        .append("materialName", materialName)
                        .append("supplierBatchNo", supplierBatchNo)
                        .append("batchNo", batchNo)
                        .append("remark", "")
                        .append("count", sumCount)
                        .append("prdCount", sumCount)
                        .append("unit", unit)
                        .append("boxCount", sumBoxCount)
                        .append("billNo", prdHouseBillNo)
                        .append("colType", "saveTask")
                        .append("_createUserId", userId)
                        .append("createUserName", userName)
                        .append("_auditUserId", userId)
                        .append("auditUserName", userName)
                        .append("taskBillNo", billNo)
                        .append("auditTime", new Date())
                        .append("isPrint", "unseal");
                if (materialNo.startsWith("04")) {
                    colDoc.append("status", BillStatus.Audit.toString());
                } else {
                    colDoc.append("status", BillStatus.Save.toString());
                }
                prdColDao.insertOne(colDoc);
                prdColDetailDao.updateManyRedirect(Criteria.where("_id").in(ids), new Document("$set", new Document("billNo", prdHouseBillNo)).append("$unset", new Document("isTemp", 1)));
            } else {
                Document colDoc = new Document("materialNo", materialNo)
                        .append("materialSpec", materialSpec)
                        .append("materialName", materialName)
                        .append("supplierBatchNo", supplierBatchNo)
                        .append("batchNo", batchNo)
                        .append("remark", "")
                        .append("count", sumCount)
                        .append("prdCount", sumCount)
                        .append("unit", unit)
                        .append("boxCount", sumBoxCount)
                        .append("billNo", prdHouseBillNo)
                        .append("colType", "saveTask")
                        .append("_createUserId", userId)
                        .append("createUserName", userName)
                        .append("_auditUserId", userId)
                        .append("auditUserName", userName)
                        .append("taskBillNo", billNo)
                        .append("auditTime", new Date())
                        .append("produceDate", produceDate)
                        .append("isPrint", "unseal");
                if (materialNo.startsWith("04")) {
                    colDoc.append("status", BillStatus.Audit.toString());
                } else {
                    colDoc.append("status", BillStatus.Save.toString());
                }
                prdColDao.insertOne(colDoc);
                prdColDetailDao.updateManyRedirect(Criteria.where("_id").in(ids), new Document("$set", new Document("billNo", prdHouseBillNo).append("produceDate", produceDate)).append("$unset", new Document("isTemp", 1)));
            }

        });

        boxNoTraceBackMap.forEach((k, v) -> {
            List<String> dataList = (List<String>) v;
//                if (dataList != null){
            for (String trace : dataList) {
                Document detailDoc = traceabilityCodeDetailDao.findOne(Criteria.where("traceabilityCode").is(trace));
                String zsmBillNo = VtuzxUtil.getString(detailDoc, "billNo");
                UpdateResult countResult = traceabilityCodeDetailDao.updateMany(Criteria.where("traceabilityCode").is(trace), new Document("boxNo", k).append("enableStatus", true));
                long count = countResult.getModifiedCount();
                traceabilityCodeDao.updateOneRedirect(Criteria.where("billNo").is(zsmBillNo), new Document("$inc", new Document("enabledCount", count).append("noEnabledCount", -count)));
            }
//                }

        });

    }

    @Override
    public VtuzxMap prdInScanBoxNo(ObjectId userId, String userName, String boxNo, String billNo) throws VtuzxException {
        String boxNoStr;
        boolean isTraceBack = false;
        if (boxNo.contains("|;")) {
            String[] boxValues = boxNo.split("\\|\\;");
            if (boxValues.length == 5) {
                String supplierNo = boxValues[0];
                String materialNo = boxValues[1];
                String batchNo = boxValues[2];
                String flowNo = boxValues[3];
                int count = Integer.parseInt(boxValues[4]);
                return getPurColMaterial(boxNo, supplierNo, materialNo, batchNo, flowNo, count);
            }
            boxNoStr = boxValues[boxValues.length - 1];
        } else if (boxNo.startsWith("http")) {
            isTraceBack = true;
            boxNoStr = boxNo;
        } else {
            boxNoStr = boxNo;
        }
        Document box = null;
        if (isTraceBack) {
            box = prdColDetailDao.findOne(Criteria.where("traceBack").in(boxNo).and("inStock").is(false));
        } else {
            box = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNoStr).and("inStock").is(false));
        }
        if (box == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        String colBillNo = VtuzxUtil.getString(box, "billNo");
        Document bill = prdColDao.findOne(Criteria.where("billNo").is(colBillNo));
        if (bill == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
        if (!BillStatus.Audit.hit(VtuzxUtil.getString(bill, "status"))) {
            throw new VtuzxException(String.format("箱号的生产收货单[%s]未审核!", colBillNo));
        }

        if (billNo.startsWith("SCRW")) {
            String taskBillNo = VtuzxUtil.getString(box, "taskBillNo");
            if (!VtuzxUtil.isEmpty(taskBillNo)) {
                //分选的判断任务号，成品的不用判断
                if (!taskBillNo.equals(billNo)) {
                    throw new VtuzxException("当前箱号不属于此任务，请确认任务号");
                }
            }

        }

        VtuzxMap res = new VtuzxMap(box);
        res.putAll(bill);
        res.remove(IVtuzxConst.Key__id);
        res.remove(IVtuzxConst.Key_createTime);
        res.remove(IVtuzxConst.Key_updateTime);
        res.remove("auditTime");
        res.remove("_createUserId");
        res.remove("_updateUserId");
        res.remove("createUserName");
        res.remove("updateUserName");
        res.remove("auditUserName");

        List<String> materialNoList = new ArrayList<>();
        Iterator<Document> detailItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (detailItr.hasNext()) {
            Document detail = detailItr.next();
            String materialNo = VtuzxUtil.getString(detail, "materialNo");
            materialNoList.add(materialNo);
        }

        String materialNo = VtuzxUtil.getString(res, "materialNo");

//        if (!materialNoList.contains(materialNo)) {
//            throw new VtuzxException("请扫描物料清单所需物料！");
//        }
        return res;
    }


    public VtuzxMap getPurColMaterial(String boxNo, String supplierNo, String materialNo, String batchNo, String flowNo, int count) throws VtuzxException {
        VtuzxMap res = new VtuzxMap();
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        if (materialDoc == null) {
            throw new VtuzxException("物料不存在");
        }
        Document supplierDoc = supplierDao.findOne(Criteria.where("fNumber").is(supplierNo));
        if (supplierDoc == null) {
            throw new VtuzxException("供应商不存在");
        }
        res.append("materialNo", materialNo);
        res.append("materialName", VtuzxUtil.getString(materialDoc, "fName"));
        res.append("materialSpec", VtuzxUtil.getString(materialDoc, "fSpecification"));
        res.append("unit", VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber"));
        res.append("supplierNo", supplierNo);
        res.append("supplierName", VtuzxUtil.getString(supplierDoc, "fName"));
        res.append("batchNo", batchNo);
        res.append("count", count);
        res.append("boxCount", 1);
        res.append("billNo", "");
        res.append("boxNo", boxNo);
        res.append("inStock", false);
        res.append("rfid", "");
        res.append("barcodeType", "BC");
        return res;
    }

    @Override
    public VtuzxMap prdInScanRfid(ObjectId userId, String userName, String billNo, List<String> rfidList) {
        Iterator<Document> boxItr = prdColDetailDao.findList(Criteria.where("rfid").in(rfidList).and("inStock").ne(true), null, 0, 0);
        List<Document> boxList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        while (boxItr.hasNext()) {
            Document box = boxItr.next();
            String colBillNo = VtuzxUtil.getString(box, "billNo");
            boxList.add(box);
            if (!billNoList.contains(colBillNo)) {
                billNoList.add(colBillNo);
            }
        }
        if (VtuzxUtil.isEmpty(boxList)) {
            return new VtuzxMap(IVtuzxConst.Key_data, new ArrayList<>());
        }
        Iterator<Document> billItr = prdColDao.findList(Criteria.where("billNo").in(billNoList).and("status").is(BillStatus.Audit.toString()), null, 0, 0);
        VtuzxMap billMap = FastUtil.itr2Map(billItr, "billNo");
        for (int i = boxList.size() - 1; i >= 0; i--) {
            Document box = boxList.get(i);
            String colBillNo = VtuzxUtil.getString(box, "billNo");
            Document bill = VtuzxUtil.getObject(billMap, colBillNo);
            if (bill == null) {
                boxList.remove(i);
                continue;
            }
            if (bill.containsKey("count")) {
                bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
            }
            box.putAll(bill);
            box.remove(IVtuzxConst.Key__id);
            box.remove(IVtuzxConst.Key_createTime);
            box.remove(IVtuzxConst.Key_updateTime);
            box.remove("auditTime");
            box.remove("_createUserId");
            box.remove("_updateUserId");
            box.remove("createUserName");
            box.remove("updateUserName");
            box.remove("auditUserName");
        }
        return new VtuzxMap(IVtuzxConst.Key_data, boxList);
    }

    @Override
    public VtuzxMap addPrdInBoxList(ObjectId userId, String userName, List<Map<String, Object>> boxList, String stockNo, String locationNo, String billNo) throws VtuzxException {
        List<String> taskMaterialNoList = new ArrayList<>();
        Iterator<Document> taskItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (taskItr.hasNext()) {
            Document taskDoc = taskItr.next();
            taskMaterialNoList.add(VtuzxUtil.getString(taskDoc, "materialNo"));
        }

        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String type = VtuzxUtil.getString(taskDoc, "type");

        for (Map<String, Object> data : boxList) {
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            if ("product".equals(type)) {
                String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
                if (!taskBillNo.equals(billNo)) {
                    throw new VtuzxException(String.format("箱号[%s]不属于当前任务的收货", boxNo));
                }
            }
        }

        for (Map<String, Object> data : boxList) {
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            List<String> traceBack = VtuzxUtil.getObject(data, "traceBack");
            VtuzxMap prdColDetail = prdInScanBoxNo(userId, userName, boxNo, billNo);
            int colBoxCount = VtuzxUtil.getInt(prdColDetail, "boxCount");
            double colCount = VtuzxUtil.getDouble(prdColDetail, "countTotal");

            List<VtuzxMap> traceBackList = new ArrayList<>();
            if (traceBack != null) {
                for (String traceNo : traceBack) {
                    VtuzxMap traceMap = new VtuzxMap("traceBackNo", traceNo).append("status", "in");
                    traceBackList.add(traceMap);
                }
            }
            String barcodeType = VtuzxUtil.getString(prdColDetail, "barcodeType");
            if ("BC".equals(barcodeType)) {
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo + "|;batch";
            } else {
                Document scanBoxDoc = prdInDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
                if (scanBoxDoc != null) {
                    throw new VtuzxException("箱号已入库!");
                }
            }
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            if ("sorting".equals(type)) {
                if (taskMaterialNoList.contains(materialNo)) {
                    throw new VtuzxException(String.format("物料[%s]添加失败,不能入库任务单下达的物料", materialNo));
                }
            }
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
            String batchNo = VtuzxUtil.getString(data, "batchNo");
            String unit = VtuzxUtil.getString(data, "unit");
            double count = VtuzxUtil.getDouble(data, "count");
            int exp = VtuzxUtil.getInt(data, "exp");
            String produceDate = VtuzxUtil.getString(data, "produceDate");
            String rfid = VtuzxUtil.getString(data, "rfid");

            Document boxMap = prdInDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo).and("isTemp").is(true).and("task").ne(false));
            if (!VtuzxUtil.isEmpty(boxMap)) {
                String createUserName = VtuzxUtil.getString(boxMap, "createUserName");
                throw new VtuzxException("箱号已存在，请勿重复添加！【扫码人员：" + createUserName + "】");
            }

            Criteria detailCond = Criteria.where("stockNo").is(stockNo);
            detailCond.and("isTemp").is(true);
            detailCond.and("materialNo").is(materialNo);
            detailCond.and("batchNo").is(batchNo);
            detailCond.and("task").is(true);
            detailCond.and("locationNo").is(locationNo);
            Document detail = prdInDetailDao.findOne(detailCond);
            Document updateVal = new Document();
            double nowColCount = 0.0;
            int nowColBoxCount = 0;

            if ("BC".equals(barcodeType)) {
                nowColCount = count;
                nowColBoxCount = 1;
            } else {
                Iterator<Document> otherColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("createTime", -1), 0, 0);
                while (otherColDetailItr.hasNext()) {
                    Document otherColDetailDoc = otherColDetailItr.next();
                    boolean inStock = VtuzxUtil.getBoolean(otherColDetailDoc, "inStock");
                    double otherColCount = VtuzxUtil.getDouble(otherColDetailDoc, "count");
                    if (!inStock) {
                        nowColCount += otherColCount;
                        nowColBoxCount++;
                    }
                }
            }

            if (detail == null) {
                updateVal.append("isTemp", true);
                updateVal.append("stockNo", stockNo);
                updateVal.append("locationNo", locationNo);
                updateVal.append("materialNo", materialNo);
                updateVal.append("materialName", materialName);
                updateVal.append("materialSpec", materialSpec);
                updateVal.append("batchNo", batchNo);
                updateVal.append("unit", unit);
                updateVal.append("_createUserId", userId);
                updateVal.append("createUserName", userName);
                updateVal.append("boxCount", 1);
                updateVal.append("count", count);
                updateVal.append("colCount", colCount);
                updateVal.append("colBoxCount", colBoxCount);
                updateVal.append("nowColCount", nowColCount);
                updateVal.append("nowColBoxCount", nowColBoxCount);
                updateVal.append("produceDate", produceDate);
                updateVal.append("exp", exp);
                updateVal.append("task", true);
            } else {
                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count)).append("$set", new Document("nowColCount", nowColCount).append("nowColBoxCount", nowColBoxCount));
            }
            ObjectId _detailId;
            if (detail == null) {
                _detailId = prdInDetailDao.insertOne(updateVal);
            } else {
                _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
                prdInDetailDao.updateByIdRedirect(_detailId, updateVal);
            }

            Document detailBox = new Document();
            detailBox.append("isTemp", true);
            detailBox.append("_detailId", _detailId);
            detailBox.append("materialNo", materialNo);
            detailBox.append("materialName", materialName);
            detailBox.append("materialSpec", materialSpec);
            detailBox.append("boxNo", boxNo);
            detailBox.append("count", count);
            detailBox.append("batchNo", batchNo);
            detailBox.append("_createUserId", userId);
            detailBox.append("createUserName", userName);
            detailBox.append("stockNo", stockNo);
            detailBox.append("locationNo", locationNo);
            detailBox.append("unit", unit);
            detailBox.append("rfid", rfid);
            detailBox.append("task", true);
            detailBox.append("barcodeType", barcodeType);
            detailBox.append("traceBack", traceBackList);
            prdInDetailBoxDao.insertOne(detailBox);
        }
        return getUserMaterialBomInMaterial(userId, stockNo);
    }

    @Override
    public void createPrdInBill(ObjectId userId, String userName, String taskBillNo, String stockNo) throws VtuzxException {
        String billNo = IXqcConst.createBillNo(BillType.CJRK);
        String heatBoxNo = "B" + new Date().getTime();
        Criteria getCond = Criteria.where("isTemp").is(true).and("task").is(true).and("_createUserId").is(userId);
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(getCond, null, 0, 0);
        double sumCount = 0d;
        int sumBoxCount = 0;

        Document task = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseName = VtuzxUtil.getString(task, "produceHouseName");
        String type = VtuzxUtil.getString(task, "type");
        //查询生产任务计划的任务数量
        double taskCount = VtuzxUtil.getDouble(task, "count");
        Document taskMaterialDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String taskMaterialNo = VtuzxUtil.getString(taskMaterialDoc, "materialNo");

        List<Document> allTraceBack = new ArrayList<>();//存放所有的追溯码
        List<String> colBoxNoList = new ArrayList<>();
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(getCond, null, 0, 0);
        List<Document> prdInDetailBoxList = new ArrayList<>();
        while (prdInDetailBoxItr.hasNext()) {
            Document box = prdInDetailBoxItr.next();
            double count = VtuzxUtil.getDouble(box, "count");
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            String boxStockNo = VtuzxUtil.getString(box, "stockNo");
            if (!stockNo.equals(boxStockNo)) {
                throw new VtuzxException("不能一次入两个仓库,请确保仓库一致");
            }
            List<Document> traceBackList = VtuzxUtil.getObject(box, "traceBack");
            if ("product".equals(type)) {
                if (!materialNo.equals(taskMaterialNo)) {
                    throw new VtuzxException("不能入库任务单之外的物料");
                }
            }
            colBoxNoList.add(boxNo);
            sumBoxCount++;
            sumCount += count;
            prdInDetailBoxList.add(box);
            allTraceBack.addAll(traceBackList);
        }

        VtuzxMap updateColBillMap = new VtuzxMap();
        Iterator<Document> purColDetailItr = prdColDetailDao.findList(Criteria.where("boxNo").in(colBoxNoList), null, 0, 0);
        while (purColDetailItr.hasNext()) {
            Document purColDetailDoc = purColDetailItr.next();
            double count = VtuzxUtil.getDouble(purColDetailDoc, "count");
            String colBillNo = VtuzxUtil.getString(purColDetailDoc, "billNo");
            VtuzxMap updateColBill = VtuzxUtil.getObject(updateColBillMap, colBillNo);
            if (VtuzxUtil.isEmpty(updateColBill)) {
                VtuzxMap smallColBillMap = new VtuzxMap();
                smallColBillMap.append("count", count).append("boxCount", 1);
                updateColBillMap.append(colBillNo, smallColBillMap);
            } else {
                double sCount = VtuzxUtil.getDouble(updateColBill, "count");
                int sBoxCount = VtuzxUtil.getInt(updateColBill, "boxCount");
                updateColBillMap.append(colBillNo, new VtuzxMap("count", sCount + count).append("boxCount", sBoxCount + 1));
            }

        }
        List<BillMaterial> prdInDetailList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        while (prdInDetailItr.hasNext()) {
            Document prdInDetail = prdInDetailItr.next();
            BillMaterial billMaterial = new BillMaterial();
            ObjectId _prdInDetailId = prdInDetail.getObjectId(IVtuzxConst.Key__id);
            billMaterial.setMaterialNo(VtuzxUtil.getString(prdInDetail, "materialNo"));
            billMaterial.setUnit(VtuzxUtil.getString(prdInDetail, "unit"));
            billMaterial.setBatchNo(VtuzxUtil.getString(prdInDetail, "batchNo"));
            billMaterial.setProduceDate(VtuzxUtil.getString(prdInDetail, "produceDate"));
            billMaterial.setExp(VtuzxUtil.getInt(prdInDetail, "exp"));
            List<BillMaterialBox> boxList = new ArrayList<>();
            for (Document boxDoc : prdInDetailBoxList) {
                ObjectId _detailId = VtuzxUtil.getObject(boxDoc, "_detailId");
                String barcodeType = VtuzxUtil.getString(boxDoc, "barcodeType");
                if (_prdInDetailId.equals(_detailId)) {
                    BillMaterialBox box = new BillMaterialBox();
                    String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
                    box.setBoxNo(boxNo);
                    box.setRfid(VtuzxUtil.getString(boxDoc, "rfid"));
                    box.setCount(VtuzxUtil.getDouble(boxDoc, "count"));
                    box.setLocationNo(VtuzxUtil.getString(prdInDetail, "locationNo"));
                    box.setTraceBack(VtuzxUtil.getObject(boxDoc, "traceBack"));
                    box.setIsTaskIn(true);
                    boxList.add(box);
                    if (!"BC".equals(barcodeType)) {
                        boxNoList.add(boxNo);
                    }
                }
                billMaterial.setBoxList(boxList);
            }
            prdInDetailList.add(billMaterial);
        }
        //查询之前对应生产任务的入库数量总和
//        Criteria prdCond = new Criteria("task").is(true);
//        prdCond.and("taskBillNo").is(taskBillNo);
//        double sumInCount = 0d;
//        Iterator<Document> prdInDocItr = prdInDao.findList(prdCond, null, 0, 0);
//        while (prdInDocItr.hasNext()) {
//            Document prdInDoc = prdInDocItr.next();
//            double count = VtuzxUtil.getDouble(prdInDoc, "count");
//            sumInCount += count;//以前的任务入库数量总和
//        }
//        Document prdTaskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
//        String materialNo = VtuzxUtil.getString(prdTaskDetailDoc, "materialNo");
//        String materialModel = VtuzxUtil.getString(prdTaskDetailDoc, "materialModel");
//        String materialName = VtuzxUtil.getString(prdTaskDetailDoc, "materialName");
//        if (sumInCount + sumCount > taskCount) {
//            prdTaskDetailDoc.replace("inType", "超计划入库");
//        } else if (sumInCount + sumCount < taskCount) {
//            prdTaskDetailDoc.replace("inType", "部分入库");
//        } else if (sumInCount + sumCount == taskCount) {
//            prdTaskDetailDoc.replace("inType", "已入库");
//        }
//        prdTaskDetailDao.updateOne(Criteria.where("billNo").is(taskBillNo), prdTaskDetailDoc);
        //修改生产任务里入库状态
        //往入库表里插入数据
        prdInDao.insertBill(userId, userName,
                new Document("billNo", billNo)
                        .append("status", BillStatus.Audit.toString())
                        .append("task", true)
                        .append("boxCount", sumBoxCount)
                        .append("count", sumCount)
                        .append("_createUserId", userId)
                        .append("createUserName", userName)
                        .append("taskBillNo", taskBillNo)
                        .append("produceHouseName", produceHouseName)
                        .append("stockNo", stockNo));


        // 更新收货单入库状态
        if (!VtuzxUtil.isEmpty(boxNoList)) {
            try {
                UpdateResult updRes = prdColDetailDao.updateMany(Criteria.where("boxNo").in(boxNoList).and("inStock").ne(true),
                        new Document("perInBillNo", billNo).append("perInTime", new Date()).append("inStock", true));
                if (updRes.getModifiedCount() != boxNoList.size()) {
                    throw new VtuzxException(IXqcConst.Msg_E_XQC_stock_pur_col_in_stock);
                }
            } catch (Exception e) {
                prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
                prdInDao.unaudit(billNo);
                throw e;
            }
        }

        //更新分录单号
        Criteria cond = new Criteria("_createUserId").is(userId).and("isTemp").is(true).and("task").is(true);
        prdInDetailDao.updateManyRedirect(cond, new Document("$unset", new Document("isTemp", 1)).append("$set", new Document("billNo", billNo)));
        prdInDetailBoxDao.updateManyRedirect(cond, new Document("$unset", new Document("isTemp", 1)).append("$set", new Document("billNo", billNo)));


        // 更新即时库存
        try {
            inventoryService.addInventory(userId, userName, BillEvent.Audit, BillType.CJRK, stockNo, billNo, prdInDetailList);

            for (String boxNo : boxNoList) {
                inventoryDetailDao.updateOne(Criteria.where("boxNo").is(boxNo), new Document("heatBoxNo", heatBoxNo).append("heatBoxNoCount", sumBoxCount));
            }

        } catch (Exception e) {
            prdInDao.deleteOne(Criteria.where("billNo").is(billNo));
            if (!VtuzxUtil.isEmpty(boxNoList)) {
                prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
            }
            throw e;
        }

        try {
            if ("product".equals(type)) {
                syncKingdeeOrderService.syncPrdInStockOrder(userId, userName, billNo, "pda", null);
            }
        } catch (Exception e) {
            _logger.error(e.getMessage(), e);
        }

        //做收货单的已入库数量重量的反写
        updateColBillMap.forEach((k, v) -> {
            VtuzxMap map = (VtuzxMap) v;
            double sCount = VtuzxUtil.getDouble(map, "count");
            int sBoxCount = VtuzxUtil.getInt(map, "boxCount");
            prdColDao.updateOneRedirect(Criteria.where("billNo").is(k), new Document("$inc", new Document("inStockCount", sCount).append("inStockBoxCount", sBoxCount)));
        });

        //入库是成品，极客云创建入库单
//        if (materialNo.startsWith("04")) {
//            //获取令牌
//            Document storeDoc = storeTokenDao.findOne(Criteria.where("type").is("kingdee"));
//            String intWarehouseCode = "XQWG00101";//仓库编码
//
//            VtuzxMap goodsMap = new VtuzxMap();//getGoodsList方法返回值
//            //需要先获取条码(skubarcode)
//            VtuzxMap goodsParam = new VtuzxMap();
//            goodsParam.append("pageIndex", 0)
//                    .append("pageSize", 1)
//                    .append("goodsNo", materialNo);
//            try {
//                goodsMap = iJiKeYunApiService.getGoodsList(storeDoc, goodsParam);
//            } catch (Exception e) {
//                throw new VtuzxException(e.getMessage());
//            }
//
//            LinkedHashMap result = VtuzxUtil.getObject(goodsMap, "result");
//            LinkedHashMap data = VtuzxUtil.getObject((Map<String, Object>) result, "data");
//            List<LinkedHashMap> goods = VtuzxUtil.getObject((Map<String, Object>) data, "goods");
//            LinkedHashMap goodsResult = goods.get(0);
//            String skuBarcode = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuBarcode");
//            String skuId = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuId");
//            String skuName = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuName");
//            //创建极客云入库单
//            VtuzxMap stockParam = new VtuzxMap();//入库参数
//            List<VtuzxMap> stockInDetailViews = new ArrayList<>();//入库申请单明细
//
//            stockInDetailViews.add(new VtuzxMap().append("relDetailId", billNo)
//                    .append("skuCount", sumCount).append("isCertified", 1)
//                    .append("skuBarcode", skuBarcode));
//            stockParam.append("intWarehouseCode", intWarehouseCode)//仓库
//                    .append("inType", 101)
//                    .append("relDataId", billNo)//关联单据编号,可随机，保证不重复即可
//                    .append("applyDate", VtuzxUtil.formatYmdHmsF(new Date()))
//                    .append("operator", userName)
//                    .append("source", "OPEN")
//                    .append("notificationCode", "100")
//                    .append("stockInDetailViews", stockInDetailViews);
//
//            //创建入库单
//            try {
//                iJiKeYunApiService.createStockIn(storeDoc, stockParam);
//            } catch (Exception e) {
//                throw new VtuzxException(e.getMessage());
//            }
//
//            //传入唯一码到极客云
//            //先判断是否是成品并且有追溯码在传
//            if (!VtuzxUtil.isEmpty(allTraceBack)) {
//                List<String> allNoList = new ArrayList<>();//所有追溯码
//                for (Document traceDoc : allTraceBack) {//先取出追溯码
//                    String traceBackNo = VtuzxUtil.getString(traceDoc, "traceBackNo");
//                    allNoList.add(traceBackNo);
//                }
//                String stringFromList = String.join(",", allNoList);//把唯一码转化成Str类型
//                //从生产任务表中查询物料编码和规格
//                VtuzxMap bizcontent = new VtuzxMap();//业务请求参数
//                bizcontent.append("goodsNo", materialNo)
//                        .append("skuName", skuName)
//                        .append("serialNoList", stringFromList)
//                        .append("snDefine2", VtuzxUtil.formatYmdHmsF(new Date()))
//                        .append("snDefine1", VtuzxUtil.formatYmdHmsF(new Date()));
//                if (!VtuzxUtil.isEmpty(stringFromList)) {
//                    try {
//                        iJiKeYunApiService.serialNoAdd(storeDoc, bizcontent);
//                    } catch (Exception e) {
//                        throw new VtuzxException(e.getMessage());
//                    }
//                }
//            }
//            //新增箱码
//            BillType billType = BillType.SCRK;
//            for (Document prdBox : prdInDetailBoxList) {
//                VtuzxMap boxParam = new VtuzxMap();//箱码总参数
//                List<VtuzxMap> boxDetailList = new ArrayList<>();//入库申请单明细
//                List<VtuzxMap> boxSerialList = new ArrayList<>();//唯一码参数
//                String boxNo = VtuzxUtil.getString(prdBox, "boxNo");
//                //获取唯一码
//                List<Map<String, Object>> traceBack = VtuzxUtil.getObject(prdBox, "traceBack");
//                for (Map<String, Object> serialMap : traceBack) {
//                    String traceBackNo = VtuzxUtil.getString(serialMap, "traceBackNo");
//                    VtuzxMap map = new VtuzxMap("sn", traceBackNo);
//                    boxSerialList.add(map);
//                }
//                Document prdColDoc = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));
//                String id = VtuzxUtil.getString(prdColDoc, "_id");
//                String batchNo = VtuzxUtil.getString(prdColDoc, "batchNo");
//                double count = VtuzxUtil.getDouble(prdColDoc, "count");
//
//                int serialCount = traceBack.size();//每个箱子的唯一码数量
//                boxDetailList.add(new VtuzxMap("goodsNo", materialNo)
//                        .append("goodsName", materialName)
//                        .append("skuId", skuId)
//                        .append("boxCount", serialCount)
//                        .append("snList", boxSerialList));
//                boxParam.append("boxCount", 1)
//                        .append("boxDetailList", boxDetailList)
//                        .append("isAuto", 3)
//                        .append("boxNo", billType.barcodeKey() + "|;" + id + "|;" + materialNo + "|;" + batchNo + "|;" + count + "|;" + boxNo);
//                try {
//                    iJiKeYunApiService.createBoxBatch(storeDoc, boxParam);
//                } catch (Exception e) {
//                    throw new VtuzxException(e.getMessage());
//                }
//            }
//        }
    }

    @Override
    public VtuzxMap getUserMaterialBomInMaterial(ObjectId userId, String stockNo) {
        List<VtuzxMap> materialBomInDetailList = new ArrayList<>();
        Iterator<Document> materialBomInDetailItr = prdInDetailDao.findList(Criteria.where("_createUserId").is(userId).and("isTemp").is(true).and("task").ne(false).and("stockNo").is(stockNo), null, 0, 0);
        while (materialBomInDetailItr.hasNext()) {
            Document materialBomInDetailDoc = materialBomInDetailItr.next();
            VtuzxMap materialBomInDetailMap = new VtuzxMap(materialBomInDetailDoc);
            String id = VtuzxUtil.removeString(materialBomInDetailMap, IVtuzxConst.Key__id);
            String createUserId = VtuzxUtil.removeString(materialBomInDetailMap, "_createUserId");
            materialBomInDetailMap.append("id", id).append("createUserId", createUserId);
            materialBomInDetailList.add(materialBomInDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomInDetailList);
    }

    @Override
    public VtuzxMap getUserMaterialBomInMaterialBox(ObjectId userId, String detailId) {
        List<VtuzxMap> materialBomInDetailBoxList = new ArrayList<>();
        Iterator<Document> materialBomInDetailBoxItr = prdInDetailBoxDao.findList(Criteria.where("_createUserId").is(userId).and("_detailId").is(new ObjectId(detailId)).and("task").ne(false), null, 0, 0);
        while (materialBomInDetailBoxItr.hasNext()) {
            Document materialBomInDetailBoxDoc = materialBomInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(materialBomInDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            materialBomInDetailBoxList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, materialBomInDetailBoxList);
    }

    @Override
    public void deleteUserMaterialBomInMaterial(ObjectId userId, String id) {
        prdInDetailDao.deleteById(FastUtil.convertId(id));
        prdInDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserMaterialBomInMaterialBox(ObjectId userId, String id) {
        Document materialBomInDetailBoxDoc = prdInDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(materialBomInDetailBoxDoc, "_detailId");
        prdInDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> materialBomInDetailBoxItr = prdInDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while (materialBomInDetailBoxItr.hasNext()) {
            Document doc = materialBomInDetailBoxItr.next();
            double materialBomInDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = materialBomInDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0 && total == 0) {
            prdInDetailDao.deleteById(_detailId);
        } else {
            prdInDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
    }

    @Override
    public VtuzxMap getPrdInList(ObjectId userId, int pageIndex, int pageSize, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("task").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = prdInDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = prdInDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = prdInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("isUpload", VtuzxUtil.getString(doc, "isUpload"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdInDetail(ObjectId userId, String billNo) {
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        String scrkBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
        String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
        String createUserName = VtuzxUtil.getString(prdInDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdInDoc, "createTime"));
        String stockNo = VtuzxUtil.getString(prdInDoc, "stockNo");
        double count = VtuzxUtil.getDouble(prdInDoc, "count");
        int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scrkBillNo)
                .append("stockNo", stockNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("count", String.format("%.2f", count))
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            VtuzxMap prdInDetailMap = new VtuzxMap(prdInDetailDoc);
            String materialNo = VtuzxUtil.getString(prdInDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(prdInDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(prdInDetailMap, "_createUserId");

            prdInDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(prdInDetailMap);
        }
        for (VtuzxMap map : dataList) {
            double fCount = VtuzxUtil.getDouble(map, "count");
            map.replace("count", String.format("%.2f", fCount));
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdInDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(cond, null, 0, 0);
        while (prdInDetailBoxItr.hasNext()) {
            Document prdInDetailBoxDoc = prdInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(prdInDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdTaskListPick(ObjectId userId, String userName, Map<String, Object> param) {
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        String type = VtuzxUtil.getString(param, "type");
        String inTaskBillNo = VtuzxUtil.getString(param, "billNo");
        Criteria cond = new Criteria();
        cond.and("type").is(type);
        if (!VtuzxUtil.isEmpty(inTaskBillNo)) {
            cond.and("billNo").regex(inTaskBillNo);
        }
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("startTime", VtuzxUtil.getInt(doc, "startTime"))
                .append("endTime", VtuzxUtil.getDouble(doc, "endTime"))
                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
                .append("produceHouseNo", VtuzxUtil.getString(doc, "produceHouseNo"))
                .append("type", VtuzxUtil.getString(doc, "type"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("businessStatus", VtuzxUtil.getString(doc, "businessStatus"))
                .append("sort", VtuzxUtil.getInt(doc, "sort"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("pick", VtuzxUtil.getBoolean(doc, "pick"))
                .append("pickStatus", VtuzxUtil.getBoolean(doc, "pickStatus"))
                .append("_auditUserId", VtuzxUtil.getString(doc, "_auditUserId"))
                .append("auditUserName", VtuzxUtil.getString(doc, "auditUserName"))
                .append("_createUserId", VtuzxUtil.getString(doc, "_createUserId"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "auditTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdTaskListSupplementReturn(ObjectId userId, String userName, Map<String, Object> param) {
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        String type = VtuzxUtil.getString(param, "type");
        String inTaskBillNo = VtuzxUtil.getString(param, "billNo");
        Criteria cond = new Criteria();
        cond.and("type").is(type).and("businessStatus").is("start").and("status").ne("close");
        if (!VtuzxUtil.isEmpty(inTaskBillNo)) {
            cond.and("billNo").regex(inTaskBillNo);
        }
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("materialBomBillNo", VtuzxUtil.getString(doc, "materialBomBillNo"))
                .append("startTime", VtuzxUtil.getInt(doc, "startTime"))
                .append("endTime", VtuzxUtil.getDouble(doc, "endTime"))
                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
                .append("produceHouseNo", VtuzxUtil.getString(doc, "produceHouseNo"))
                .append("type", VtuzxUtil.getString(doc, "type"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("businessStatus", VtuzxUtil.getString(doc, "businessStatus"))
                .append("sort", VtuzxUtil.getInt(doc, "sort"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("pick", VtuzxUtil.getBoolean(doc, "pick"))
                .append("pickStatus", VtuzxUtil.getBoolean(doc, "pickStatus"))
                .append("_auditUserId", VtuzxUtil.getString(doc, "_auditUserId"))
                .append("auditUserName", VtuzxUtil.getString(doc, "auditUserName"))
                .append("_createUserId", VtuzxUtil.getString(doc, "_createUserId"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "auditTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getSortingSaveTaskMaterial(ObjectId userId, String userName, Map<String, Object> param) {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        Document header = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        List<String> childMaterialNoList = new ArrayList<>();
        Iterator<Document> materialBomDetailItr = materialBomDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (materialBomDetailItr.hasNext()) {
            Document materialBomDetailDoc = materialBomDetailItr.next();
            String childMaterialNo = VtuzxUtil.getString(materialBomDetailDoc, "childMaterialNo");
            childMaterialNoList.add(childMaterialNo);
        }


        List<VtuzxMap> bomList = new ArrayList<>();
        Iterator<Document> bomItr = bomDao.findList(Criteria.where("childList.childMaterialNo").in(childMaterialNoList), null, 0, 0);
        while (bomItr.hasNext()) {
            Document bomDoc = bomItr.next();
            VtuzxMap bomMap = new VtuzxMap(bomDoc);
            bomMap.remove("_id");
            bomMap.remove("updateTime");
            bomMap.remove("createTime");
            bomList.add(bomMap);
        }


        return new VtuzxMap(IVtuzxConst.Key_data, bomList).append("header", header);
    }

    @Override
    public void materialBomPickConfirm(ObjectId userId, String userName, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        materialBomPickDetailDao.updateOne(Criteria.where("taskBillNo").is(billNo).and("isTemp").is(true), new Document("confirm", true));
    }

    @Override
    public VtuzxMap getBomSortingList(ObjectId userId, String userName, Map<String, Object> param) {
        String key = VtuzxUtil.getString(param, "key");
        Criteria cond = new Criteria();
        cond.and("childList.numerator").is("1.0").and("childList.denominator").is("1.0");
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("childList.childMaterialNo").regex("^" + key + ".*$", "i"), Criteria.where("childList.childMaterialName").regex("^.*" + key + ".*$", "i"));
        }
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        List<Document> arrList = new ArrayList<>();
        Iterator<Document> bomItr = bomDao.getChildList(cond, pageIndex, pageSize);
        while (bomItr.hasNext()) {
            Document bomDoc = bomItr.next();
            Document child = VtuzxUtil.getObject(bomDoc, "_id");
            arrList.add(child);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, arrList);
    }

    @Override
    public void deletePrdTaskBill(ObjectId userId, String billNo) throws VtuzxException {
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String status = VtuzxUtil.getString(prdTaskDoc, "status");
        if (status.equals("audit")) {
            throw new VtuzxException("不能删除已审核的单据");
        }
        prdTaskDao.deleteOne(Criteria.where("billNo").is(billNo));
        prdTaskDetailDao.deleteMany(Criteria.where("billNo").is(billNo));
        materialBomDao.deleteOne(Criteria.where("taskBillNo").is(billNo));
        materialBomDetailDao.deleteMany(Criteria.where("taskBillNo").is(billNo));
    }


    @Override
    public VtuzxMap getPrdTaskBillNo(ObjectId userId, String name, String key, int pageIndex, int pageSize) {
        List<VtuzxMap> billNoList = new ArrayList<>();
        Iterator<Document> prdTaskItr = prdTaskDao.findList(Criteria.where("billNo").regex(key), new Document("createTime", -1), pageIndex, 5);
        while (prdTaskItr.hasNext()) {
            VtuzxMap map = new VtuzxMap();
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            map.append("key", billNo);
            billNoList.add(map);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, billNoList);
    }

    @Override
    public void closePrdOrder(ObjectId userId, List<String> billNoList) throws VtuzxException {
        for (String billNo : billNoList) {
            Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
            Document inDoc = prdInDao.findOne(Criteria.where("taskBillNo").is(billNo));
            if (!VtuzxUtil.isEmpty(pickDoc) && VtuzxUtil.isEmpty(inDoc)) {
                throw new VtuzxException(String.format("单号[%s]已领料未入库,不能关闭", billNo));
            }
            prdTaskDao.updateMany(Criteria.where("billNo").is(billNo), new Document("status", "close"));
            materialBomDao.updateMany(Criteria.where("taskBillNo").is(billNo), new Document("status", "close").append("taskStatus", "close"));
            materialBomPickDao.updateMany(Criteria.where("taskBillNo").is(billNo), new Document("status", "close"));
            materialBomSupplementDao.updateMany(Criteria.where("taskBillNo").is(billNo), new Document("status", "close"));
            materialBomReturnDao.updateMany(Criteria.where("taskBillNo").is(billNo), new Document("status", "close"));
        }
    }

//    @Override
//    public VtuzxMap addDesaltingInStockBox(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
//        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
//
//        for (Map<String, Object> data: boxList) {
//            String stockNo = VtuzxUtil.getString(data, "stockNo");
//            String locationNo = VtuzxUtil.getString(data, "locationNo");
//            String boxNo = VtuzxUtil.getString(data, "boxNo");
//            String materialNo = VtuzxUtil.getString(data, "materialNo");
//            String materialName = VtuzxUtil.getString(data, "materialName");
//            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
//            String batchNo = VtuzxUtil.getString(data, "batchNo");
//            String unit = VtuzxUtil.getString(data, "unit");
//            double count = VtuzxUtil.getDouble(data, "count");
//            int exp = VtuzxUtil.getInt(data, "exp");
//            String produceDate = VtuzxUtil.getString(data, "produceDate");
//            String rfid = VtuzxUtil.getString(data, "rfid");
//
//            Document boxMap = desaltingInStockDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo).and("isTemp").is(true));
//            if (!VtuzxUtil.isEmpty(boxMap)) {
//                throw new VtuzxException("箱号已存在，请勿重复添加");
//            }
//
//            Criteria detailCond = Criteria.where("stockNo").is(stockNo);
//            detailCond.and("isTemp").is(true);
//            detailCond.and("materialNo").is(materialNo);
//            detailCond.and("batchNo").is(batchNo);
//            Document detail = desaltingInStockDetailDao.findOne(detailCond);
//            Document updateVal = new Document();
//
//            if (detail == null) {
//                updateVal.append("isTemp", true);
//                updateVal.append("stockNo", stockNo);
//                updateVal.append("locationNo", locationNo);
//                updateVal.append("materialNo", materialNo);
//                updateVal.append("materialName", materialName);
//                updateVal.append("materialSpec", materialSpec);
//                updateVal.append("batchNo", batchNo);
//                updateVal.append("unit", unit);
//                updateVal.append("_createUserId", userId);
//                updateVal.append("createUserName", userName);
//                updateVal.append("boxCount", 1);
//                updateVal.append("count", count);
//                updateVal.append("produceDate", produceDate);
//                updateVal.append("exp", exp);
//            } else {
//                updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count));
//            }
//            ObjectId _detailId;
//            if (detail == null) {
//                _detailId = desaltingInStockDetailDao.insertOne(updateVal);
//            } else {
//                _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
//                desaltingInStockDetailDao.updateByIdRedirect(_detailId, updateVal);
//            }
//
//            Document detailBox = new Document();
//            detailBox.append("isTemp", true);
//            detailBox.append("_detailId", _detailId);
//            detailBox.append("materialNo", materialNo);
//            detailBox.append("materialName", materialName);
//            detailBox.append("materialSpec", materialSpec);
//            detailBox.append("boxNo", boxNo);
//            detailBox.append("count", count);
//            detailBox.append("batchNo", batchNo);
//            detailBox.append("_createUserId", userId);
//            detailBox.append("createUserName", userName);
//            detailBox.append("stockNo", stockNo);
//            detailBox.append("locationNo", locationNo);
//            detailBox.append("unit", unit);
//            detailBox.append("rfid", rfid);
//            desaltingInStockDetailBoxDao.insertOne(detailBox);
//        }
//        return null;
//    }

    @Override
    public void createDesaltingInStockBill(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");

        //查询领料单,变品退料的品不允许是领料或者补料的品
//        List<String> materialNoList = new ArrayList<>();
//        Iterator<Document> pickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
//        while (pickItr.hasNext()){
//            Document pickDoc = pickItr.next();
//            String materialNo = VtuzxUtil.getString(pickDoc,"materialNo");
//            if (!materialNoList.contains(materialNo)){
//                materialNoList.add(materialNo);
//            }
//        }
//        Iterator<Document> supplimentItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
//        while (supplimentItr.hasNext()){
//            Document supplimentDoc = supplimentItr.next();
//            String materialNo = VtuzxUtil.getString(supplimentDoc,"materialNo");
//            if (!materialNoList.contains(materialNo)){
//                materialNoList.add(materialNo);
//            }
//        }
        VtuzxMap boxMap = new VtuzxMap();
        for (Map<String, Object> data : boxList) {
            List<Map<String, Object>> dataList = new ArrayList<>();
            String materialNo = VtuzxUtil.getString(data, "materialNo");
//            if(!materialNo.startsWith("0303")){//排除水带
//                if (materialNoList.contains(materialNo)){
//                    throw new VtuzxException("变品退料的品不允许是领料或者补料的品");
//                }
//            }

            String batchNo = VtuzxUtil.getString(data, "batchNo");
            List<Map<String, Object>> list = VtuzxUtil.getObject(boxMap, materialNo + '_' + batchNo);
            if (list == null) {
                dataList.add(data);
                boxMap.append(materialNo + '_' + batchNo, dataList);
            } else {
                list.add(data);
            }
        }

        boxMap.forEach((k, v) -> {
            String billNo = IXqcConst.createBillNo(BillType.CJSH);
            List<Document> documentList = new ArrayList<>();
            List<VtuzxMap> prdColList = (List<VtuzxMap>) v;
            Map<String, Object> map = prdColList.get(0);
            String materialNo = VtuzxUtil.getString(map, "materialNo");
            String materialSpec = VtuzxUtil.getString(map, "materialModel");
            String materialName = VtuzxUtil.getString(map, "materialName");
            String headerComment = VtuzxUtil.getString(map, "comment");
            String headerUnit = VtuzxUtil.getString(map, "unitName");
            String batchNo = VtuzxUtil.getString(map, "batchNo");

            double totalCount = 0d;
            int totalBoxCount = 0;
            for (Map<String, Object> prdCol : prdColList) {
                String comment = VtuzxUtil.getString(prdCol, "comment");
                String boxNo = "A02" + new Date().getTime();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String unit = VtuzxUtil.getString(prdCol, "unit");
                double count = VtuzxUtil.getDouble(prdCol, "count");
                totalCount += count;
                totalBoxCount++;

                Document colDetailDoc = new Document("count", count)
                        .append("unit", unit)
                        .append("billNo", billNo)
                        .append("taskBillNo", taskBillNo)
                        .append("boxNo", boxNo)
                        .append("comment", comment)
                        .append("inStock", false)
                        .append("colType", "desaltingIn")
                        .append("_insertUserId", userId)
                        .append("insertUserName", userName);
                prdColDetailDao.insertOne(colDetailDoc);

            }


            Document colDoc = new Document("materialNo", materialNo)
                    .append("materialSpec", materialSpec)
                    .append("materialName", materialName)
                    .append("batchNo", batchNo)
                    .append("remark", headerComment)
                    .append("count", totalCount)
                    .append("prdCount", totalCount)
                    .append("unit", headerUnit)
                    .append("boxCount", totalBoxCount)
                    .append("billNo", billNo)
                    .append("colType", "desaltingIn")
                    .append("status", BillStatus.Save.toString())
                    .append("_createUserId", userId)
                    .append("createUserName", userName)
                    .append("_auditUserId", userId)
                    .append("auditUserName", userName)
                    .append("taskBillNo", taskBillNo)
                    .append("auditTime", new Date())
                    .append("isPrint", "unseal");
            prdColDao.insertOne(colDoc);
        });
    }

//    @Override
//    public VtuzxMap getUserDesaltingInStockMaterial(ObjectId userId, String stockNo) {
//        List<VtuzxMap> desaltingInStockDetailList = new ArrayList<>();
//        Iterator<Document> desaltingInStockDetailItr = desaltingInStockDetailDao.findList(Criteria.where("_createUserId").is(userId).and("isTemp").is(true).and("task").ne(false).and("stockNo").is(stockNo), null, 0, 0);
//        while (desaltingInStockDetailItr.hasNext()) {
//            Document desaltingInStockDetailDoc = desaltingInStockDetailItr.next();
//            VtuzxMap desaltingInStockDetailMap = new VtuzxMap(desaltingInStockDetailDoc);
//            String id = VtuzxUtil.removeString(desaltingInStockDetailMap, IVtuzxConst.Key__id);
//            String createUserId = VtuzxUtil.removeString(desaltingInStockDetailMap, "_createUserId");
//            desaltingInStockDetailMap.append("id", id).append("createUserId", createUserId);
//            desaltingInStockDetailList.add(desaltingInStockDetailMap);
//        }
//        return new VtuzxMap(IVtuzxConst.Key_data, desaltingInStockDetailList);
//    }
//
//    @Override
//    public VtuzxMap getUserDesaltingInStockMaterialBox(ObjectId userId, String detailId) {
//        List<VtuzxMap> desaltingInStockDetailBoxList = new ArrayList<>();
//        Iterator<Document> desaltingInStockDetailBoxItr = desaltingInStockDetailBoxDao.findList(Criteria.where("_createUserId").is(userId).and("_detailId").is(new ObjectId(detailId)).and("task").ne(false), null, 0, 0);
//        while (desaltingInStockDetailBoxItr.hasNext()) {
//            Document desaltingInStockDetailBoxDoc = desaltingInStockDetailBoxItr.next();
//            VtuzxMap boxMap = new VtuzxMap(desaltingInStockDetailBoxDoc);
//            boxMap.remove(IVtuzxConst.Key_createTime);
//            boxMap.remove(IVtuzxConst.Key_updateTime);
//            boxMap.remove("_createUserId");
//            boxMap.remove("createUserName");
//            boxMap.remove("_updateUserId");
//            boxMap.remove("updateUserName");
//            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
//            desaltingInStockDetailBoxList.add(boxMap);
//        }
//        return new VtuzxMap(IVtuzxConst.Key_data, desaltingInStockDetailBoxList);
//    }
//
//    @Override
//    public void deleteUserDesaltingInStockMaterial(ObjectId userId, String id) {
//        desaltingInStockDetailDao.deleteById(FastUtil.convertId(id));
//        desaltingInStockDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
//    }
//
//    @Override
//    public void deleteUserDesaltingInStockMaterialBox(ObjectId userId, String id) {
//        Document desaltingInStockDetailBoxDoc = desaltingInStockDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
//        ObjectId _detailId = VtuzxUtil.getObject(desaltingInStockDetailBoxDoc, "_detailId");
//        desaltingInStockDetailBoxDao.deleteById(FastUtil.convertId(id));
//        Iterator<Document> desaltingInStockDetailBoxItr = desaltingInStockDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
//        int boxCount = 0;
//        double total = 0;
//        while (desaltingInStockDetailBoxItr.hasNext()) {
//            Document doc = desaltingInStockDetailBoxItr.next();
//            double desaltingInStockDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
//            total = desaltingInStockDetailBoxCount + total;
//            boxCount++;
//        }
//        if (boxCount == 0 && total == 0) {
//            desaltingInStockDetailDao.deleteById(_detailId);
//        } else {
//            desaltingInStockDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
//        }
//    }

    @Override
    public VtuzxMap getDesaltingInStockBill(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("desalting").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = prdInDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = prdInDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = prdInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
                .append("isUpload", VtuzxUtil.getString(doc, "isUpload"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getDesaltingInStockBillDetail(ObjectId userId, String billNo) {
        Document desaltingInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        String scrkBillNo = VtuzxUtil.getString(desaltingInDoc, "billNo");
        String taskBillNo = VtuzxUtil.getString(desaltingInDoc, "taskBillNo");
        String createUserName = VtuzxUtil.getString(desaltingInDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(desaltingInDoc, "createTime"));
        String stockNo = VtuzxUtil.getString(desaltingInDoc, "stockNo");
        double count = VtuzxUtil.getDouble(desaltingInDoc, "count");
        int boxCount = VtuzxUtil.getInt(desaltingInDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scrkBillNo)
                .append("stockNo", stockNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("count", count)
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> desaltingInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (desaltingInDetailItr.hasNext()) {
            Document desaltingInDetailDoc = desaltingInDetailItr.next();
            VtuzxMap desaltingInDetailMap = new VtuzxMap(desaltingInDetailDoc);
            String materialNo = VtuzxUtil.getString(desaltingInDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(desaltingInDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(desaltingInDetailMap, "_createUserId");

            desaltingInDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(desaltingInDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getDesaltingInStockBillDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> desaltingInDetailBoxItr = prdInDetailBoxDao.findList(cond, null, 0, 0);
        while (desaltingInDetailBoxItr.hasNext()) {
            Document desaltingInDetailBoxDoc = desaltingInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(desaltingInDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPrdTaskBillNumberReturn(ObjectId userId, String billNo) {
        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String materialBomBillNo = VtuzxUtil.getString(taskDoc, "materialBomBillNo");
        String produceHouseName = VtuzxUtil.getString(taskDoc, "produceHouseName");
        return new VtuzxMap("materialBomBillNo", materialBomBillNo).append("produceHouse", produceHouseName);
    }

    @Override
    public VtuzxMap inventoryTest(ObjectId userId, String stockNo) {
        List<Document> invList = new ArrayList<>();
        List<String> idList = new ArrayList<>();
        Iterator<Document> invItr = inventoryDao.findList(Criteria.where("stockNo").is(stockNo), null, 0, 0);
//        Iterator<Document> invItr = inventoryDao.findList(Criteria.where("_id").is(FastUtil.convertId("6254f91fae77a23e14b21587")).and("count").gt(0),null, 0, 0);
        while (invItr.hasNext()) {
            Document invDoc = invItr.next();
            invList.add(invDoc);
        }


        for (Document iv : invList) {
            String id = VtuzxUtil.getString(iv, "_id");
            double count = VtuzxUtil.getDouble(iv, "count");
            int boxCount = VtuzxUtil.getInt(iv, "boxCount");
            double sum = 0d;
            int boxSum = 0;
            Iterator<Document> detailItr = inventoryDetailDao.findList(Criteria.where("_inventoryId").in(FastUtil.convertId(id)).and("status").is("in"), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detail = detailItr.next();
                double dCount = VtuzxUtil.getDouble(detail, "count");
                sum += dCount;
                boxSum++;
            }
            boolean comp1 = BigDecimal.valueOf(count).setScale(6, RoundingMode.HALF_UP).compareTo(BigDecimal.valueOf(sum).setScale(6, RoundingMode.HALF_UP)) == 0;

            if (!comp1 || boxCount != boxSum) {
                idList.add(id);
            }
        }

        _logger.info("id:" + idList);
        return new VtuzxMap("idList", idList);
    }

    @Override
    public void prdTaskEnd(ObjectId userId, String userName, String billNo) throws VtuzxException {
        Document task = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String type = VtuzxUtil.getString(task, "type");

        if ("sorting".equals(type)) {
            List<Map<String, Object>> boxList = new ArrayList<>();
            List<String> colBillNoList = new ArrayList<>();
            //排除退料
            Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(billNo).and("colType").ne("return"), null, 0, 0);
            while (prdColItr.hasNext()) {
                Document prdColDoc = prdColItr.next();
                Map<String, Object> prdColMap = new LinkedHashMap<>(prdColDoc);
                String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                colBillNoList.add(colBillNo);
                boxList.add(prdColMap);
            }

            Iterator<Document> prdColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").in(colBillNoList), null, 0, 0);
            while (prdColDetailItr.hasNext()) {
                Document document = prdColDetailItr.next();
                boolean inStock = VtuzxUtil.getBoolean(document, "inStock");
                if (!inStock) {
                    throw new VtuzxException("有关联收货未入库!");
                }
            }
            //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
            //把领料和补料的仓库先放到一个集合中
            Map<String, Object> stockMap = new HashMap<>();//k:（领料和补料）物料加批次加仓库,v:document
            Map<String, Object> returnMap = new HashMap<>();//k:物料加批次，v:仓库
            Iterator<Document> bomPickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
            while (bomPickItr.hasNext()) {
                Document bomPickDoc = bomPickItr.next();
                String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
                Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                returnMap.put(materialNo + "_" + batchNo, stockNo);
                if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                    stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                } else {
                    double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                    double count = VtuzxUtil.getDouble(bomPickDoc, "count");
                    bomPickDoc.replace("count", returnCount + count);
                    stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                }
            }

            Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
            while (bomSupplementItr.hasNext()) {
                Document bomSupplementDoc = bomSupplementItr.next();
                String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
                Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                returnMap.put(materialNo + "_" + batchNo, stockNo);
                if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                    stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                } else {
                    double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                    double count = VtuzxUtil.getDouble(bomSupplementDoc, "count");
                    bomSupplementDoc.replace("count", returnCount + count);
                    stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                }
            }

            List<Document> returnList = new ArrayList<>();//退料需要做调拨的

            Iterator<Document> returnItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
            while (returnItr.hasNext()) {
                Document returnDoc = returnItr.next();
                String stockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                String materialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                if (VtuzxUtil.isEmpty(returnDocument)) {//说明退料仓库和领料仓库不一致，需要做调拨
                    returnList.add(returnDoc);
                }
            }

//            try {
//                //做生产订单
//                syncKingdeeOrderService.syncPrdOrderSorting(userId, userName, billNo, "pda", boxList);
//                Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
//                String llBillNo = VtuzxUtil.getString(pickDoc, "billNo");
//                //做调拨
//                syncKingdeeOrderService.syncStockTransferOrder(userId, userName, llBillNo, "pda");
//                //做领料
//                syncKingdeeOrderService.syncPrdPickOrderSorting(userId, userName, llBillNo, "pda", boxList);
//                //入库
//                List<Document> inList = new ArrayList<>();
//                List<String> inHeaderBillNoList = new ArrayList<>();
//                Iterator<Document> prdInDocItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
//                while (prdInDocItr.hasNext()) {
//                    Document prdInDoc = prdInDocItr.next();
//                    String inHeaderBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
//                    inHeaderBillNoList.add(inHeaderBillNo);
//                }
//
//                Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("billNo").in(inHeaderBillNoList), null, 0, 0);
//                while (prdInItr.hasNext()) {
//                    inList.add(prdInItr.next());
//                }
//                String inBillNo = VtuzxUtil.getString(inList.get(0), "billNo");
//                syncKingdeeOrderService.syncPrdInStockOrderSorting(userId, userName, inBillNo, "pda");
//                //如果料的仓库和领料或者补料的仓库不一致的话需要做调拨单
//                if (!returnList.isEmpty()){
//                    syncKingdeeOrderAllocation(userId, userName,returnList,returnMap,billNo,"pda");
//                }
//
//            } catch (Exception e) {
//                _logger.info(e.getMessage());
//            }
        } else {
            Document prdCol = prdColDao.findOne(Criteria.where("taskBillNo").is(billNo));
            String colBillNo = VtuzxUtil.getString(prdCol, "billNo");
            Iterator<Document> prdColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").is(colBillNo), null, 0, 0);
            while (prdColDetailItr.hasNext()) {
                Document document = prdColDetailItr.next();
                boolean inStock = VtuzxUtil.getBoolean(document, "inStock");
                if (!inStock) {
                    throw new VtuzxException("有关联收货未入库!");
                }
            }
        }
        prdTaskDao.updateOne(Criteria.where("billNo").is(billNo), new Document("businessStatus", "end"));
    }

    @Override
    public VtuzxMap getReturnInList(ObjectId userId, int pageIndex, int pageSize, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("return").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if ((!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            if (!VtuzxUtil.isEmpty(batchNo)) {
                pickCond.and("batchNo").regex(batchNo);
            }
            Iterator<Document> materialBomPickDetailItr = prdInDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        if (!VtuzxUtil.isEmpty(boxNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Iterator<Document> materialBomPickDetailItr = prdInDetailBoxDao.findList(Criteria.where("boxNo").regex(boxNo), null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            long materialBomPickCount = prdInDao.count(cond.and("billNo").in(pickBillNoList));
            Iterator<Document> materialBomPickItr = prdInDao.findList(cond, new Document("createTime", -1), pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_total, materialBomPickCount).append(IVtuzxConst.Key_data, pickList);
        }
        VtuzxPage page = prdInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("_createUserId", VtuzxUtil.getObject(doc, "_createUserId"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("produceHouseName", VtuzxUtil.getString(doc, "produceHouseName"))
                .append("taskBillNo", VtuzxUtil.getString(doc, "taskBillNo"))
                .append("isUpload", VtuzxUtil.getString(doc, "isUpload"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getReturnInDetail(ObjectId userId, String billNo) {
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        String scrkBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
        String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
        String createUserName = VtuzxUtil.getString(prdInDoc, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdInDoc, "createTime"));
        String stockNo = VtuzxUtil.getString(prdInDoc, "stockNo");
        double count = VtuzxUtil.getDouble(prdInDoc, "count");
        int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");
        VtuzxMap header = new VtuzxMap("billNo", scrkBillNo)
                .append("stockNo", stockNo)
                .append("taskBillNo", taskBillNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("count", count)
                .append("boxCount", boxCount);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            VtuzxMap prdInDetailMap = new VtuzxMap(prdInDetailDoc);
            String materialNo = VtuzxUtil.getString(prdInDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            String _id = VtuzxUtil.removeString(prdInDetailMap, IVtuzxConst.Key__id);
            String _createUserId = VtuzxUtil.removeString(prdInDetailMap, "_createUserId");

            prdInDetailMap.append("_id", _id)
                    .append("_createUserId", _createUserId)
                    .append("unit", fBaseUnitIdFName);
            dataList.add(prdInDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getReturnInDetailBox(ObjectId userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(cond, null, 0, 0);
        while (prdInDetailBoxItr.hasNext()) {
            Document prdInDetailBoxDoc = prdInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(prdInDetailBoxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void saveTaskAddPrdCol(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException, InterruptedException {

        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        String taskBillNo = VtuzxUtil.getString(boxList.get(0), "billNo");


        String serialNo = VtuzxUtil.getString(boxList.get(0), "serialNo");//最后一次扫码信息
        if (!VtuzxUtil.isEmpty(serialNo)) {
            //判断追溯是否重复
            Document prdColDetailDoc = prdColDetailDao.findOne(Criteria.where("traceBack").in(serialNo));
            if (!VtuzxUtil.isEmpty(prdColDetailDoc)) {
                throw new VtuzxException("追溯码重复");
            }
            // 存在校验
            {
                long count = traceabilityCodeDetailDao.count(Criteria.where("traceabilityCode").is(serialNo).and("enableStatus").is(false));
                if (count < 0) {
                    throw new VtuzxException("追溯码不存在");
                }
            }
        }
        //避免箱号重复
        String boxStart = "";
        if (name.contains("bian")) {
            boxStart = "A022";
        } else if (name.contains("dong")) {
            boxStart = "A023";
        } else if (name.contains("pan")) {
            boxStart = "A024";
        } else {
            boxStart = "A021";
        }
        Document prdTskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseName = VtuzxUtil.getString(prdTskDoc, "produceHouseName");
        if (!produceHouseName.equals("干参包装车间")) {//如果不是干参包装车间每次都重新排序
            for (Map<String, Object> box : boxList) {
                double count = 0;
                String id = VtuzxUtil.getString(box, "id");
                String materialNo = VtuzxUtil.getString(box, "materialNo");
                String materialName = VtuzxUtil.getString(box, "materialName");
                String materialModel = VtuzxUtil.getString(box, "materialModel");
                String supplierNo = VtuzxUtil.getString(box, "supplierNo");
                String supplierName = VtuzxUtil.getString(box, "supplierName");
                int standard = VtuzxUtil.getInt(box, "standard");
                int currentCount = VtuzxUtil.getInt(box, "currentCount");
                boolean isDelete = VtuzxUtil.getBoolean(box, "isDelete");
                String billNo = VtuzxUtil.getString(box, "billNo");
                String unit = VtuzxUtil.getString(box, "unit");
                String unitName = VtuzxUtil.getString(box, "unitName");
                String department = VtuzxUtil.getString(box, "department");
                String batchNo = VtuzxUtil.getString(box, "batchNo").replaceAll("\\s+", "");
                double sumCount = VtuzxUtil.getDouble(box, "count");
                int orderNum = (int) VtuzxUtil.getInt(box, "orderNum");//排序序号

                double traceCount = VtuzxUtil.getDouble(box, "traceCount");//追溯重量
                List<String> traceBack = VtuzxUtil.getObject(box, "traceBack");
                if (traceBack.size() < standard && !VtuzxUtil.isEmpty(serialNo)) {
                    traceBack.add(serialNo);//添加最后一次扫码信息
                    currentCount++;//已扫数量
                }
                if (traceCount == 1 || traceCount == 0) {
                    count = sumCount;
                } else {
                    count = traceBack.size() * traceCount;
                }

                String oldBoxNo = VtuzxUtil.getString(box, "boxNo");

                Thread.sleep(10);
                //防止箱号重复
                String orininBoxNo = boxStart + new Date().getTime();
                String boxNo = orininBoxNo.substring(0, orininBoxNo.length() - 1);
                Document updateDoc = new Document("materialNo", materialNo)
                        .append("materialModel", materialModel)
                        .append("materialName", materialName)
                        .append("supplierNo", supplierNo)
                        .append("supplierName", supplierName)
                        .append("unit", unit)
                        .append("unitName", unitName)
//                    .append("boxNo", boxNo)
                        .append("batchNo", batchNo)
                        .append("count", count * 100 / 100)
                        .append("inStock", false)
                        .append("comment", "")
                        .append("_insertUserId", userId)
                        .append("insertUserName", name)
                        .append("isTemp", true)
                        .append("noPrint", true)
                        .append("taskBillNo", billNo)
                        .append("department", department)
                        .append("standard", standard)
                        .append("isDelete", isDelete)
                        .append("currentCount", currentCount)
                        .append("traceCount", traceCount)
                        .append("orderNum", String.format("%04d", orderNum + 1))
                        .append("traceBack", traceBack);
                if (VtuzxUtil.isEmpty(oldBoxNo)) {//如果已经有箱号就不添加了
                    updateDoc.append("boxNo", boxNo);
                }
                if (VtuzxUtil.isEmpty(id)) {
                    prdColDetailDao.insertOne(updateDoc);
                    _logger.info(String.format("添加的箱号信息:%s", updateDoc.get(boxNo)));
                } else {
                    updateDoc.remove("noPrint");
                    prdColDetailDao.updateById(id, updateDoc);
                }
            }
        } else {
            for (Map<String, Object> box : boxList) {
                double count = 0;
                String id = VtuzxUtil.getString(box, "id");
                String materialNo = VtuzxUtil.getString(box, "materialNo");
                String materialName = VtuzxUtil.getString(box, "materialName");
                String materialModel = VtuzxUtil.getString(box, "materialModel");
                String supplierNo = VtuzxUtil.getString(box, "supplierNo");
                String supplierName = VtuzxUtil.getString(box, "supplierName");
                int standard = VtuzxUtil.getInt(box, "standard");
                int currentCount = VtuzxUtil.getInt(box, "currentCount");
                boolean isDelete = VtuzxUtil.getBoolean(box, "isDelete");
                String billNo = VtuzxUtil.getString(box, "billNo");
                String unit = VtuzxUtil.getString(box, "unit");
                String unitName = VtuzxUtil.getString(box, "unitName");
                String department = VtuzxUtil.getString(box, "department");
                String batchNo = VtuzxUtil.getString(box, "batchNo").replaceAll("\\s+", "");
                double sumCount = VtuzxUtil.getDouble(box, "count");
                int orderNum = VtuzxUtil.getInt(box, "orderNum");//排序序号

                double traceCount = VtuzxUtil.getDouble(box, "traceCount");//追溯重量
                List<String> traceBack = VtuzxUtil.getObject(box, "traceBack");
                if (traceBack.size() < standard && !VtuzxUtil.isEmpty(serialNo)) {
                    traceBack.add(serialNo);//添加最后一次扫码信息
                    currentCount++;//已扫数量
                }
                sumCount = currentCount;
                if (traceCount == 1 || traceCount == 0) {
                    count = sumCount;
                } else {
                    count = traceBack.size() * traceCount;
                }
//            double count = traceBack.size() * traceCount;
                String oldBoxNo = VtuzxUtil.getString(box, "boxNo");
                double orderCount = prdColDetailDao.count(Criteria.where("taskBillNo").is(billNo).and("isTemp").ne(true));//查询之前入库数
                int order = (int) (orderCount + orderNum + 1);

                Thread.sleep(10);
                String orininBoxNo = boxStart + new Date().getTime();
                String boxNo = orininBoxNo.substring(0, orininBoxNo.length() - 1);
                Document updateDoc = new Document("materialNo", materialNo)
                        .append("materialModel", materialModel)
                        .append("materialName", materialName)
                        .append("supplierNo", supplierNo)
                        .append("supplierName", supplierName)
                        .append("unit", unit)
                        .append("unitName", unitName)
//                    .append("boxNo", boxNo)
                        .append("batchNo", batchNo)
                        .append("count", count * 100 / 100)
                        .append("inStock", false)
                        .append("comment", "")
                        .append("_insertUserId", userId)
                        .append("insertUserName", name)
                        .append("isTemp", true)
                        .append("noPrint", true)
                        .append("taskBillNo", billNo)
                        .append("department", department)
                        .append("standard", standard)
                        .append("isDelete", isDelete)
                        .append("currentCount", currentCount)
                        .append("traceCount", traceCount)
                        .append("orderNum", String.format("%04d", order))
                        .append("traceBack", traceBack);
                if (VtuzxUtil.isEmpty(oldBoxNo)) {//如果已经有箱号就不添加了
                    updateDoc.append("boxNo", boxNo);
                }
                if (VtuzxUtil.isEmpty(id)) {
                    prdColDetailDao.insertOne(updateDoc);
                    _logger.info(String.format("添加的箱号信息:%s", updateDoc.get(boxNo)));
                } else {
                    updateDoc.remove("noPrint");
                    prdColDetailDao.updateById(id, updateDoc);
                }
            }
        }

    }

    @Override
    public void saveTaskDeletePrdCol(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        //删除当前箱码信息后，把当前箱码之后创建的箱码信息查询出来，并重新排列序号
        String id = VtuzxUtil.getString(param, "id");
        Document prdColDoc = prdColDetailDao.findById(id);
        String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
        Date createTime = VtuzxUtil.getObject(prdColDoc, "createTime");
        String number = VtuzxUtil.getString(prdColDoc, "orderNum");
        String insertUserName = VtuzxUtil.getString(prdColDoc, "insertUserName");
        if (!name.equals(insertUserName)) {
            throw new VtuzxException("请不要删除其他用户信息");
        }
        prdColDetailDao.deleteById(id);
        if (VtuzxUtil.isEmpty(number)) {
            return;
        }
        //查询出当前任务号的并且创建时间在删除的箱码创建时间之后的
        List<Document> tempList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("createTime").gt(createTime).and("isTemp").is(true), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdColDetailDoc = prdColItr.next();
            String orderNum = VtuzxUtil.getString(prdColDetailDoc, "orderNum");
            if (!VtuzxUtil.isEmpty(orderNum)) {
                tempList.add(prdColDetailDoc);
            }
        }
        for (Document doc : tempList) {
            String _id = VtuzxUtil.getString(doc, "_id");
            String orderNum = VtuzxUtil.getString(doc, "orderNum");
            int orderNo = Integer.parseInt(orderNum);
            orderNo -= 1;
//            doc.replace("orderNum",String.format("%04d",orderNo));
            prdColDetailDao.updateById(_id, new Document("orderNum", String.format("%04d", orderNo)));

        }
    }

    @Override
    public VtuzxMap saveTaskGetPrdColList(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> detailItr = prdColDetailDao.findList(Criteria.where("isTemp").is(true).and("taskBillNo").is(billNo), null, 0, 0);
        while (detailItr.hasNext()) {
            Document detailDoc = detailItr.next();
            VtuzxMap data = new VtuzxMap(detailDoc);
            data.append("_insertUserId", VtuzxUtil.removeString(data, "_insertUserId"));
            data.append("id", VtuzxUtil.removeString(data, "_id"));
            dataList.add(data);
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void saveTaskAddPrdColTraceBack(ObjectId userId, String name, Map<String, Object> param) {
//        String id = VtuzxUtil.getString(param, "id");
//        String id = VtuzxUtil.getString(param, "id");
//        Document colDoc = prdColDetailDao.findById(id);
//        List<String> traceBack = VtuzxUtil.getObject(colDoc, "traceBack");
//        if (VtuzxUtil.isEmpty(traceBack)) {
//
//        }
    }

    @Override
    public void saveTaskNoPrint(ObjectId userId, String name, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        prdColDetailDao.updateById(id, new Document("noPrint", true));
    }

    @Override
    public VtuzxMap getPrdColBatch(ObjectId userId, String name, Map<String, Object> param) {
        String billNoStr = VtuzxUtil.getString(param, "billNoList");
        String[] splitList = billNoStr.split(",");
        VtuzxMap dataMap = new VtuzxMap();
        //单据头数据
        Date createTime = null;
        List<String> billNoList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("billNo").in(splitList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdColDoc = prdColItr.next();
            String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
            String taskBillNo = VtuzxUtil.getString(prdColDoc, "taskBillNo");
//            createTime = VtuzxUtil.getObject(prdColDoc,"createTime");
            dataMap.append(colBillNo, prdColDoc);
            billNoList.add(taskBillNo);
        }
        //去生产任务表里查询当前任务的创建时间
        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNoList.get(0)));
        createTime = VtuzxUtil.getObject(taskDoc, "createTime");
        //把date转换成localdateTime获取当天开始时间和结束时间
        Instant instant = createTime.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        LocalDateTime startTime = localDateTime.with(LocalTime.MIN);
        LocalDateTime endTime = localDateTime.with(LocalTime.MAX);
        //再转化成String类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localStartTime = startTime.format(formatter);
        String localEndTime = endTime.format(formatter);
        //根据任务编号的时间查询这一天的数据
        List<VtuzxMap> dayList = new ArrayList<>();
        Criteria cond = new Criteria();
        cond.and("createTime").gte(VtuzxUtil.parseDate(localStartTime)).lte(VtuzxUtil.parseDate(localEndTime));
        Iterator<Document> prdColDayItr = prdTaskDao.findList(cond, new Document("createTime", 1), 0, 0);
        while (prdColDayItr.hasNext()) {
            Document prdColDoc = prdColDayItr.next();
            VtuzxMap dayMap = new VtuzxMap(prdColDoc);
            dayList.add(dayMap);
        }
        //获取当前任务的序号
        int orderNum = 0;
        for (VtuzxMap map : dayList) {
            orderNum++;
            String taskBillNo = VtuzxUtil.getString(map, "billNo");
            if (billNoList.get(0).equals(taskBillNo)) {
                break;
            }
        }
        //收货信息详细表
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> prdColDetailItr = prdColDao.findList(Criteria.where("billNo").in(splitList), null, 0, 0);
        while (prdColDetailItr.hasNext()) {
            Document detailDoc = prdColDetailItr.next();
            String colTypeName = VtuzxUtil.getString(detailDoc, "colType");
            String materialNo = VtuzxUtil.getString(detailDoc, "materialNo");
            String materialName = VtuzxUtil.getString(detailDoc, "materialName");
            String materialSpec = VtuzxUtil.getString(detailDoc, "materialSpec");
            String batchNo = VtuzxUtil.getString(detailDoc, "batchNo");
            String billNo = VtuzxUtil.getString(detailDoc, "billNo");
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            VtuzxMap detailMap = new VtuzxMap();
            detailMap.append("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialSpec", materialSpec)
                    .append("batchNo", batchNo)
                    .append("billNo", billNo)
                    .append("count", String.format("%.2f", count));
            if (colTypeName.equals("prdCol")) {
                detailMap.append("colTypeName", "车间收货");
            } else if (colTypeName.equals("saveTask")) {
                detailMap.append("colTypeName", "任务收货");
            } else if (colTypeName.equals("desaltingIn")) {
                detailMap.append("colTypeName", "生产变品");
            } else if (colTypeName.equals("return")) {
                detailMap.append("colTypeName", "退货收货");
            }
            //单据体数据
            dataList.add(detailMap);
        }

        //prdColDetailDao 车间收货单据体表
        //prdColDao 车间收货单据头表
//        for (Document data: dataList) {
//            String detailBillNo = VtuzxUtil.getString(data, "billNo");
//            Document headerDoc = VtuzxUtil.getObject(dataMap, detailBillNo);
//            data.append("materialNo", VtuzxUtil.getString(headerDoc, "materialNo"));
//            data.append("materialName", VtuzxUtil.getString(headerDoc, "materialName"));
//            data.append("materialSpec", VtuzxUtil.getString(headerDoc, "materialSpec"));
//            data.append("batchNo", VtuzxUtil.getString(headerDoc, "batchNo"));
//            data.append("unit", VtuzxUtil.getString(headerDoc, "unit"));
//        }

        Document prdTaskDocTime = prdTaskDao.findOne(Criteria.where("billNo").is(billNoList.get(0)));
        String taskCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDocTime, "createTime"));
        //单据头数据
        Document header = new Document();
        double count = 0;
//        SimpleDateFormat sdf = new SimpleDateFormat("YY-MM-dd");
        for (String key : dataMap.keySet()) {
            Document prdCol = (Document) dataMap.get(key);
            String taskBillNo = VtuzxUtil.getString(prdCol, "taskBillNo");
            String taskMaterialNo = VtuzxUtil.getString(prdCol, "materialNo");
            count += VtuzxUtil.getDouble(prdCol, "count");
            String createUserName = VtuzxUtil.getString(prdCol, "createUserName");
            Date auditTime = VtuzxUtil.getObject(prdCol, "auditTime");
            String billNo = VtuzxUtil.getString(prdCol, "billNo");
            //String colType = VtuzxUtil.getString(prdCol,"colType");
            Document prdTaskDoc = null;
            prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
            String produceHouseName = "";
            String applyName = "";
            if (prdTaskDoc != null) {
                produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
                applyName = VtuzxUtil.getString(prdTaskDoc, "createUserName");//入库申请人
            }

            header = new Document("taskBillNo", taskBillNo)
                    .append("count", String.format("%.2f", count))
                    .append("createUserName", createUserName)
                    .append("applyName", applyName)
//                    .append("auditTime", VtuzxUtil.formatDate(auditTime,sdf))
                    .append("auditTime", auditTime)
                    .append("billNo", billNo)
                    .append("produceHouseName", VtuzxUtil.parseDate(produceHouseName))
                    .append("taskCreateTime", taskCreateTime)//任务创建时间
                    .append("orderNum", orderNum);
            //成品需要添加上库管信息,干参是肖斌,半干和单冻是冠冠
            if (taskMaterialNo.startsWith("0401")) {
                header.append("wareHouseName", "肖斌");
            } else if (taskMaterialNo.startsWith("0402") || taskMaterialNo.startsWith("0403")) {
                header.append("wareHouseName", "刘冠冠");
                //海参花和海参肠也属于刘冠冠
            } else if (taskMaterialNo.startsWith("050106003") || taskMaterialNo.startsWith("0599060")) {
                header.append("wareHouseName", "刘冠冠");
            } else {
                header.append("wareHouseName", createUserName);
            }
        }


        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialPickBillTask(ObjectId userId, String name, Map<String, Object> param) {
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String type = VtuzxUtil.getString(param, "type");
        List<VtuzxMap> dataList = new ArrayList<>();

        if ("pick".equals(type)) {
            Iterator<Document> pickDocItr = materialBomPickDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("status").is("save"), null, 0, 0);
            while (pickDocItr.hasNext()) {
                Document pickDoc = pickDocItr.next();
                VtuzxMap pickMap = new VtuzxMap(pickDoc);
                pickMap.append("id", VtuzxUtil.removeString(pickMap, "_id"));
                dataList.add(pickMap);
            }
        } else if ("other".equals(type)) {
            Iterator<Document> pickDocItr = otherOutDao.findList(Criteria.where("status").is("save").and("createUserName").is(name)
                    , new Document("createTime", -1), 0, 0);
            while (pickDocItr.hasNext()) {
                Document pickDoc = pickDocItr.next();
                VtuzxMap pickMap = new VtuzxMap(pickDoc);
                pickMap.append("id", VtuzxUtil.removeString(pickMap, "_id"));
                dataList.add(pickMap);
            }
        } else {
            Iterator<Document> pickDocItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("status").is("save"), null, 0, 0);
            while (pickDocItr.hasNext()) {
                Document pickDoc = pickDocItr.next();
                VtuzxMap pickMap = new VtuzxMap(pickDoc);
                pickMap.append("id", VtuzxUtil.removeString(pickMap, "_id"));
                dataList.add(pickMap);
            }
        }


        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterialByBox(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        List<String> boxNoList = VtuzxUtil.getObject(param, "boxNo");
        String boxNoKey = boxNoList.get(0);
        String boxNo = "";
        if (boxNoKey.contains("|;")) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 5) {
                boxNo = boxNoKey;
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
                boxNo = boxNo + "|;batch";
            } else {
                boxNo = boxValues[boxValues.length - 1];
            }
        } else {
            boxNo = boxNoKey;
        }
        Document colDetailDoc = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));
        if (VtuzxUtil.isEmpty(colDetailDoc)) {
            throw new VtuzxException("箱号不存在");
        }
        String colBillNo = VtuzxUtil.getString(colDetailDoc, "billNo");
        Document colDoc = prdColDao.findOne(Criteria.where("billNo").is(colBillNo));
        String colTaskBillNo = VtuzxUtil.getString(colDoc, "taskBillNo");
        if (VtuzxUtil.isEmpty(colTaskBillNo)) {
            throw new VtuzxException("箱号未关联生产任务单号");
        }

        List<String> colAllDocList = new ArrayList<>();
        Iterator<Document> colAllDocItr = prdColDao.findList(Criteria.where("taskBillNo").is(colTaskBillNo), null, 0, 0);
        while (colAllDocItr.hasNext()) {
            Document colAllDoc = colAllDocItr.next();
            String billNo = VtuzxUtil.getString(colAllDoc, "billNo");
            String status = VtuzxUtil.getString(colAllDoc, "status");
            String materialNo = VtuzxUtil.getString(colAllDoc, "materialNo");
            if ("audit".equals(status) && (materialNo.startsWith("04") || materialNo.startsWith("05"))) {
                colAllDocList.add(billNo);
            }
        }
        if (colAllDocList.size() == 0) {
            throw new VtuzxException("请确认扫描的箱码物料是否是成品，或订单是否审核");
        }

        List<String> billNoList = new ArrayList<>();
        List<Document> detailList = new ArrayList<>();
        Iterator<Document> prdColDetailItr = prdColDetailDao.findList(Criteria.where("billNo").in(colAllDocList).and("inStock").is(false), null, 0, 0);
        while (prdColDetailItr.hasNext()) {
            Document prdColDetailDoc = prdColDetailItr.next();
            boolean inStock = VtuzxUtil.getBoolean(prdColDetailDoc, "inStock");
            String billNo = VtuzxUtil.getString(prdColDetailDoc, "billNo");
            if (!inStock) {
                detailList.add(prdColDetailDoc);
                billNoList.add(billNo);
            }
        }

        List<Document> prdColList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdColDoc = prdColItr.next();
            prdColList.add(prdColDoc);
        }

        for (Document detail : detailList) {
            String headerBillNo = VtuzxUtil.getString(detail, "billNo");
            for (Document prdCol : prdColList) {
                String detailBillNo = VtuzxUtil.getString(prdCol, "billNo");
                String taskBillNo = VtuzxUtil.getString(prdCol, "taskBillNo");
                String materialNo = VtuzxUtil.getString(prdCol, "materialNo");
                String materialName = VtuzxUtil.getString(prdCol, "materialName");
                String materialSpec = VtuzxUtil.getString(prdCol, "materialSpec");
                String batchNo = VtuzxUtil.getString(prdCol, "batchNo");
                String produceDate = VtuzxUtil.getString(prdCol, "produceDate");
                String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdCol, "createTime"));
                int inStockBoxCount = VtuzxUtil.getInt(prdCol, "inStockBoxCount");
                double inStockCount = VtuzxUtil.getDouble(prdCol, "inStockCount");
                double exp = VtuzxUtil.getDouble(prdCol, "exp");
                if (headerBillNo.equals(detailBillNo)) {
                    detail.append("taskBillNo", taskBillNo);
                    detail.append("materialNo", materialNo);
                    detail.append("materialName", materialName);
                    detail.append("materialSpec", materialSpec);
                    detail.append("batchNo", batchNo);
                    detail.append("inStockBoxCount", inStockBoxCount);
                    detail.append("inStockCount", inStockCount);
                    detail.append("produceDate", produceDate);
                    detail.append("exp", exp);
                }
            }
        }


        return new VtuzxMap(IVtuzxConst.Key_data, detailList);
    }

    @Override
    public void createSimplePrdIn(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException {
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String locationNo = VtuzxUtil.getString(param, "locationNo");
        List<String> prdBoxNoList = new ArrayList<>();

        List<Document> prdBoxList = new ArrayList<>();//箱子层添加集合
        List<String> prdColBillNoList = new ArrayList<>();//车间收货单号
        for (Map<String, Object> box : boxList) {
            String taskBillNo = VtuzxUtil.getString(box, "taskBillNo");
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            String materialName = VtuzxUtil.getString(box, "materialName");
            String materialSpec = VtuzxUtil.getString(box, "materialSpec");
            String unit = VtuzxUtil.getString(box, "unit");
            String batchNo = VtuzxUtil.getString(box, "batchNo");
            String billNo = VtuzxUtil.getString(box, "billNo");
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            VtuzxMap prdColDetail = prdInScanBoxNo(userId, name, boxNo, billNo);
            String barcodeType = VtuzxUtil.getString(prdColDetail, "barcodeType");

            List<String> traceBack = VtuzxUtil.getObject(box, "traceBack");
            List<VtuzxMap> traceBackList = new ArrayList<>();
            if (traceBack != null) {
                for (String traceNo : traceBack) {
                    VtuzxMap traceMap = new VtuzxMap("traceBackNo", traceNo).append("status", "in");
                    traceBackList.add(traceMap);
                }
            }

            String rfid = VtuzxUtil.getString(box, "rfid");
            double count = VtuzxUtil.getDouble(box, "count");
            if (!prdColBillNoList.contains(billNo)) {
                prdColBillNoList.add(billNo);
            }
            if (!prdBoxNoList.contains(boxNo)) {
                prdBoxNoList.add(boxNo);
            }
            Document detailBox = new Document();
            detailBox.append("isTemp", true);
            detailBox.append("materialNo", materialNo);
            detailBox.append("materialName", materialName);
            detailBox.append("materialSpec", materialSpec);
            detailBox.append("boxNo", boxNo);
            detailBox.append("count", count);
            detailBox.append("batchNo", batchNo);
            detailBox.append("_createUserId", userId);
            detailBox.append("createUserName", name);
            detailBox.append("stockNo", stockNo);
            detailBox.append("locationNo", locationNo);
            detailBox.append("unit", unit);
            detailBox.append("rfid", rfid);
            detailBox.append("task", true);
            detailBox.append("simple", true);
            detailBox.append("barcodeType", barcodeType);
            detailBox.append("traceBack", traceBackList);
            detailBox.append("taskBillNo", taskBillNo);
            detailBox.append("prdColBillNo", billNo);//箱子层添加车间收货编号，以便添加detailId
            prdBoxList.add(detailBox);
        }
        //先判断是否有入库的箱号
        Long prdBoxCount = prdInDetailBoxDao.count(Criteria.where("boxNo").in(prdBoxNoList));
        if (prdBoxCount > 0) {
            throw new VtuzxException("箱号已入库");
        }
        //先添加箱子层，后添加detail层然后反写箱子层的detailid
        prdInDetailBoxDao.insertMany(prdBoxList);
        //根据车间收货单号查询箱子的总数和重量
        List<Document> prdInDetailListItr = new ArrayList<>();
        Iterator<Document> sumCount = prdInDetailBoxDao.findSumCount(null, prdColBillNoList);
        while (sumCount.hasNext()) {
            Document sumDoc = sumCount.next();
            prdInDetailListItr.add(sumDoc);
        }
        List<ObjectId> detailIdList = new ArrayList<>();
        //添加detail层数据并反写box层数据
        for (Document detail : prdInDetailListItr) {
            String prdColBillNo = VtuzxUtil.getString(detail, "_id");
            double count = VtuzxUtil.getDouble(detail, "sumCount");
            int boxCount = VtuzxUtil.getInt(detail, "sumBoxCount");
            Document boxDoc = prdInDetailBoxDao.findOne(Criteria.where("prdColBillNo").is(prdColBillNo));
            String taskBillNo = VtuzxUtil.getString(boxDoc, "taskBillNo");
            String materialNo = VtuzxUtil.getString(boxDoc, "materialNo");
            String materialName = VtuzxUtil.getString(boxDoc, "materialName");
            String materialSpec = VtuzxUtil.getString(boxDoc, "materialSpec");
            String unit = VtuzxUtil.getString(boxDoc, "unit");
            String batchNo = VtuzxUtil.getString(boxDoc, "batchNo");
            String produceDate = VtuzxUtil.getString(boxDoc, "produceDate");
            String billNo = VtuzxUtil.getString(boxDoc, "billNo");
            String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
//            VtuzxMap prdColDetail = prdInScanBoxNo(userId, name, boxNo, billNo);
            double exp = VtuzxUtil.getDouble(boxDoc, "exp");

            Document updateVal = new Document();
            updateVal.append("isTemp", true);
            updateVal.append("stockNo", stockNo);
            updateVal.append("locationNo", locationNo);
            updateVal.append("materialNo", materialNo);
            updateVal.append("materialName", materialName);
            updateVal.append("materialSpec", materialSpec);
            updateVal.append("batchNo", batchNo);
            updateVal.append("unit", unit);
            updateVal.append("_createUserId", userId);
            updateVal.append("createUserName", name);
            updateVal.append("boxCount", boxCount);
            updateVal.append("count", count);
            updateVal.append("colCount", count);
            updateVal.append("colBoxCount", boxCount);
            updateVal.append("nowColCount", count);
            updateVal.append("nowColBoxCount", boxCount);
            updateVal.append("produceDate", produceDate);
            updateVal.append("exp", exp);
            updateVal.append("task", true);
            updateVal.append("simple", true);
            updateVal.append("taskBillNo", taskBillNo);
            ObjectId objectId = prdInDetailDao.insertOne(updateVal);
            if (!detailIdList.contains(objectId)) {
                detailIdList.add(objectId);
            }
            //反写box层数据
            prdInDetailBoxDao.updateManyRedirect(Criteria.where("prdColBillNo").is(prdColBillNo), new Document("$set", new Document("prdColBillNo", 1)).append("$set", new Document("_detailId", objectId)));
        }

        //第一次提交没有完成，第二次再次提交的话就会出现入库重复的情况，如果根据是否是临时数据去查的话会有问题
        //因为第一次提交的还没入库的话第二次的就会跟第一次混在一起
        //Criteria getCond = Criteria.where("isTemp").is(true).and("task").is(true).and("simple").is(true).and("_createUserId").is(userId);
        Criteria getCond = Criteria.where("_id").in(detailIdList);
        Criteria boxCond = Criteria.where("_detailId").in(detailIdList);
        List<Document> prdInDetailList = new ArrayList<>();
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(getCond, null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            prdInDetailList.add(prdInDetailDoc);
        }

        Iterator<Document> prdInDetailBoxItr = prdInDetailBoxDao.findList(boxCond, null, 0, 0);
        List<Document> prdInDetailBoxList = new ArrayList<>();
        while (prdInDetailBoxItr.hasNext()) {
            Document box = prdInDetailBoxItr.next();
            double count = VtuzxUtil.getDouble(box, "count");
            prdInDetailBoxList.add(box);
        }

        VtuzxMap boxMap = new VtuzxMap();//key:任务单号  val:任务单号对应的detail层集合
        for (Document prdInDetail : prdInDetailList) {
            String taskBillNo = VtuzxUtil.getString(prdInDetail, "taskBillNo");
            List<Document> saveBoxList = VtuzxUtil.getObject(boxMap, taskBillNo);
            if (saveBoxList == null) {
                List<Document> saveList = new ArrayList<>();
                saveList.add(prdInDetail);
                boxMap.append(taskBillNo, saveList);
            } else {
                saveBoxList.add(prdInDetail);
            }
        }


        List<Document> otherOutList = new ArrayList<>();//包材需要出库的集合
        List<String> taskBillNoList = new ArrayList<>();//包材需要出库的箱号
        boxMap.forEach((k, v) -> {
            String prdInBillNo = IXqcConst.createBillNo(BillType.CJRK);
            List<Document> dataList = (List<Document>) v;
            String materialNo = VtuzxUtil.getString(dataList.get(0), "materialNo");
//            String detailBatchNo = VtuzxUtil.getString(dataList.get(0), "batchNo");//批号
            String prdTaskBillNo = VtuzxUtil.getString(dataList.get(0), "taskBillNo");
            //物料是干参的需要做包材的其他出库
            if (materialNo.startsWith("040")) {
                if (!taskBillNoList.contains(prdTaskBillNo)) {
                    taskBillNoList.add(prdTaskBillNo);
                }
                otherOutList.addAll(dataList);
            }
            List<String> allTraceBack = new ArrayList<>();//存放唯一码
            List<Document> prdColDetailList = new ArrayList<>();
            double tSumCount = 0d;
            int tSumBoxCount = 0;
            for (Document data : dataList) {
                double count = VtuzxUtil.getDouble(data, "count");
                int boxCount = VtuzxUtil.getInt(data, "boxCount");
                tSumCount += count;
                tSumBoxCount += boxCount;
            }
            //根据任务单号查询车间信息
            Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(k));
            String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
            prdInDao.insertBill(userId, name,
                    new Document("billNo", prdInBillNo)
                            .append("status", BillStatus.Audit.toString())
                            .append("task", true)
                            .append("simple", true)
                            .append("produceHouseName", produceHouseName)
                            .append("materialNo", materialNo)
                            .append("boxCount", tSumBoxCount)
                            .append("count", tSumCount)
                            .append("_createUserId", userId)
                            .append("createUserName", name)
                            .append("taskBillNo", k)
                            .append("stockNo", stockNo));
            //出库
            List<BillMaterial> prdInDetailBillList = new ArrayList<>();
            List<String> boxNoList = new ArrayList<>();
            for (Document prdInDetail : prdInDetailList) {
                List<String> updateColBoxNoList = new ArrayList<>();
                BillMaterial billMaterial = new BillMaterial();
                ObjectId _prdInDetailId = prdInDetail.getObjectId(IVtuzxConst.Key__id);
                billMaterial.setMaterialNo(VtuzxUtil.getString(prdInDetail, "materialNo"));
                billMaterial.setUnit(VtuzxUtil.getString(prdInDetail, "unit"));
                billMaterial.setBatchNo(VtuzxUtil.getString(prdInDetail, "batchNo"));
                billMaterial.setProduceDate(VtuzxUtil.getString(prdInDetail, "produceDate"));
                billMaterial.setExp(VtuzxUtil.getInt(prdInDetail, "exp"));
                List<BillMaterialBox> boxInnerList = new ArrayList<>();
                for (Document boxDoc : prdInDetailBoxList) {
                    ObjectId _detailId = VtuzxUtil.getObject(boxDoc, "_detailId");
                    String barcodeType = VtuzxUtil.getString(boxDoc, "barcodeType");
                    String taskBillNo = VtuzxUtil.getString(boxDoc, "taskBillNo");
                    if (_prdInDetailId.equals(_detailId) && taskBillNo.equals(k)) {
                        BillMaterialBox box = new BillMaterialBox();
                        String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
                        box.setBoxNo(boxNo);
                        box.setRfid(VtuzxUtil.getString(boxDoc, "rfid"));
                        box.setCount(VtuzxUtil.getDouble(boxDoc, "count"));
                        box.setLocationNo(VtuzxUtil.getString(prdInDetail, "locationNo"));
                        box.setTraceBack(VtuzxUtil.getObject(boxDoc, "traceBack"));
                        box.setIsTaskIn(true);
                        boxInnerList.add(box);
                        if (!"BC".equals(barcodeType)) {
                            boxNoList.add(boxNo);
                        }
                        updateColBoxNoList.add(boxNo);
                    }
                    billMaterial.setBoxList(boxInnerList);
                }
                prdInDetailBillList.add(billMaterial);
                // 更新收货单入库状态
                if (!VtuzxUtil.isEmpty(updateColBoxNoList)) {
                    try {
                        UpdateResult updRes = prdColDetailDao.updateMany(Criteria.where("boxNo").in(updateColBoxNoList).and("inStock").ne(true),
                                new Document("perInBillNo", prdInBillNo).append("perInTime", new Date()).append("inStock", true));
                        if (updRes.getModifiedCount() != updateColBoxNoList.size()) {
                            throw new VtuzxException(IXqcConst.Msg_E_XQC_stock_pur_col_in_stock);
                        }
                        //反写收货单的已入库重量和数量
//                        List<String> prdColNoList = new ArrayList<>();
                        Iterator<Document> prdColDetailItr = prdColDetailDao.findList(Criteria.where("boxNo").in(updateColBoxNoList), null, 0, 0);
                        while (prdColDetailItr.hasNext()) {
                            Document detailDoc = prdColDetailItr.next();
                            prdColDetailList.add(detailDoc);
                            String billNo = VtuzxUtil.getString(detailDoc, "billNo");
                            double count = VtuzxUtil.getDouble(detailDoc, "count");
                            prdColDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("inStockCount", count).append("inStockBoxCount", 1)));
                        }
                    } catch (Exception e) {
                        prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(updateColBoxNoList),
                                new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
                        prdInDao.unaudit(prdInBillNo);
                        _logger.info(e.getMessage());
                    }
                }
            }
            for (Document boxDoc : prdInDetailBoxList) {//存放唯一码
                List<Document> traceBack = VtuzxUtil.getObject(boxDoc, "traceBack");
                String taskBillNo = VtuzxUtil.getString(boxDoc, "taskBillNo");
                for (Document trace : traceBack) {
                    String traceBackNo = VtuzxUtil.getString(trace, "traceBackNo");
                    if (prdTaskBillNo.equals(taskBillNo)) {
                        allTraceBack.add(traceBackNo);
                    }
                }
            }

            //更新分录单号
            Criteria cond = new Criteria("_createUserId").is(userId).and("isTemp").is(true).and("task").is(true).and("simple").is(true).and("taskBillNo").is(k);
            prdInDetailDao.updateManyRedirect(cond, new Document("$unset", new Document("isTemp", 1)).append("$set", new Document("billNo", prdInBillNo)));
            prdInDetailBoxDao.updateManyRedirect(cond, new Document("$unset", new Document("isTemp", 1)).append("$set", new Document("billNo", prdInBillNo)));

            // 更新即时库存
            try {
                inventoryService.addInventory(userId, name, BillEvent.Audit, BillType.CJRK, stockNo, prdInBillNo, prdInDetailBillList);
            } catch (Exception e) {
                prdInDao.deleteOne(Criteria.where("billNo").is(prdInBillNo));
                if (!VtuzxUtil.isEmpty(boxNoList)) {
                    prdColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                            new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
                }
                _logger.info(e.getMessage());
            }
            if (materialNo.startsWith("04") || materialNo.startsWith("05")) {
                //获取令牌
                Document storeDoc = storeTokenDao.findOne(Criteria.where("type").is("kingdee"));


                VtuzxMap goodsMap = new VtuzxMap();//getGoodsList方法返回值
                VtuzxMap goodsParam = new VtuzxMap();
                goodsParam.append("pageIndex", 0)
                        .append("pageSize", 1)
                        .append("goodsNo", materialNo);
                try {
                    goodsMap = iJiKeYunApiService.getGoodsList(storeDoc, goodsParam);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }

                LinkedHashMap result = VtuzxUtil.getObject(goodsMap, "result");
                LinkedHashMap data = VtuzxUtil.getObject((Map<String, Object>) result, "data");
                List<LinkedHashMap> goods = VtuzxUtil.getObject((Map<String, Object>) data, "goods");
                LinkedHashMap goodsResult = goods.get(0);
                String skuBarcode = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuBarcode");
                String skuId = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuId");
                String materialModel = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuName");//物料规格
                for (Document dataDetail : dataList){
                    double count = VtuzxUtil.getDouble(dataDetail, "count");
                    String detailBatchNo = VtuzxUtil.getString(dataDetail, "batchNo");//批号
                    String intWarehouseCode = "";//仓库编码
                    String relDataId = "";
                    if (detailBatchNo.startsWith("BN")){
                        relDataId = prdInBillNo + "BN";
                        intWarehouseCode = "XQBB00068";//新工厂委外仓
                    } else {
                        relDataId = prdInBillNo;
                        intWarehouseCode = "XQWG00101";//仓库编码
                    }
                    //创建极客云入库单
                    VtuzxMap stockParam = new VtuzxMap();//入库参数
                    List<VtuzxMap> stockInDetailViews = new ArrayList<>();//入库申请单明细
                    stockInDetailViews.add(new VtuzxMap().append("relDetailId", prdInBillNo)
                            .append("skuCount", count).append("isCertified", 1)
                            .append("skuBarcode", skuBarcode));
                    stockParam.append("inWarehouseCode", intWarehouseCode)//仓库
                            .append("inType", 101)
                            .append("relDataId", relDataId)//关联单据编号,可随机，保证不重复即可
                            .append("applyDate", VtuzxUtil.formatYmdHmsF(new Date()))
                            .append("operator", name)
                            .append("source", "OPEN")
                            .append("notificationCode", "100")
                            .append("stockInDetailViews", stockInDetailViews);
                    //创建入库单
                    try {
                        iJiKeYunApiService.createStockIn(storeDoc, stockParam);
                    } catch (Exception e) {
                        _logger.info(e.getMessage());
                    }
                }


                //如果有追溯码传追溯码
                if (allTraceBack != null && allTraceBack.size() > 0) {
                    createSerial(storeDoc, allTraceBack, materialNo, materialModel);
                }
                //新增箱码
                for (Document prdBox : prdInDetailBoxList) {
                    BillType billType = BillType.SCRK;
                    String taskBillNo = VtuzxUtil.getString(prdBox, "taskBillNo");
                    if (prdTaskBillNo.equals(taskBillNo)) {//判断是当前任务的在创建箱码
                        VtuzxMap boxParam = new VtuzxMap();//箱码总参数
                        List<VtuzxMap> boxDetailList = new ArrayList<>();//入库申请单明细
                        List<VtuzxMap> boxSerialList = new ArrayList<>();//唯一码参数
                        String boxNo = VtuzxUtil.getString(prdBox, "boxNo");
                        String materialName = VtuzxUtil.getString(prdBox, "materialName");
                        String id = "";
                        String batchNo = VtuzxUtil.getString(prdBox, "batchNo");
                        double count = VtuzxUtil.getDouble(prdBox, "count");
                        for (Document prdCol : prdColDetailList) {
                            String prdBoxNo = VtuzxUtil.getString(prdCol, "boxNo");
                            if (boxNo.equals(prdBoxNo)) {
                                id = VtuzxUtil.getString(prdCol, "_id");
                            }
                        }
                        //获取箱子参数唯一码
                        List<Map<String, Object>> traceBack = VtuzxUtil.getObject(prdBox, "traceBack");
                        for (Map<String, Object> serialMap : traceBack) {
                            String traceBackNo = VtuzxUtil.getString(serialMap, "traceBackNo");
                            VtuzxMap map = new VtuzxMap("sn", traceBackNo);
                            boxSerialList.add(map);
                        }
                        if (boxSerialList.size() >= 0 && boxDetailList != null) {//如果有追溯码
                            int serialCount = traceBack.size();//每个箱子的唯一码数量
                            boxDetailList.add(new VtuzxMap("goodsNo", materialNo)
                                    .append("goodsName", materialName)
                                    .append("skuId", skuId)
                                    .append("boxCount", serialCount)
                                    .append("snList", boxSerialList));
                            boxParam.append("boxCount", 1)
                                    .append("boxDetailList", boxDetailList)
                                    .append("isAuto", 3)
                                    .append("boxNo", billType.barcodeKey() + "|;" + id + "|;" + materialNo + "|;" + "888888" + "|;" + count + "|;" + boxNo);
                        } else {//如果没有追溯码
                            boxDetailList.add(new VtuzxMap("goodsNo", materialNo)
                                    .append("goodsName", materialName)
                                    .append("skuId", skuId)
                                    .append("boxCount", count));
                            boxParam.append("boxCount", 1)
                                    .append("boxDetailList", boxDetailList)
                                    .append("isAuto", 3)
                                    .append("boxNo", billType.barcodeKey() + "|;" + id + "|;" + materialNo + "|;" + batchNo + "|;" + count + "|;" + boxNo);
                        }
                        try {
                            iJiKeYunApiService.createBoxBatch(storeDoc, boxParam);
                        } catch (Exception e) {
                            _logger.info("箱码未上传的原因" + e.getMessage());
                        }
                    }
                }
            }
        });
        //干参成品做包材的其他出
        try {
            saveOtherOutBaoCai(otherOutList, userId, name, taskBillNoList);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }

    }

    private void saveOtherOutBaoCai(List<Document> otherOutList, ObjectId userId, String name, List<String> taskBillNoList) throws Exception {
        List<VtuzxMap> baoCaiList = new ArrayList<>();//包材最终需要出库的
        //干参成品做包材的其他出
        if (!VtuzxUtil.isEmpty(otherOutList)) {
            List<Document> materialBomList = new ArrayList<>();
            Iterator<Document> materialBomItr = materialBomDetailDao.findList(Criteria.where("taskBillNo").in(taskBillNoList), null, 0, 0);
            while (materialBomItr.hasNext()) {
                Document materialBomDoc = materialBomItr.next();
                String childMaterialNo = VtuzxUtil.getString(materialBomDoc, "childMaterialNo");
                //只要包材的数据
                if (childMaterialNo.startsWith("06")) {
                    materialBomList.add(materialBomDoc);
                }

            }
            //根据用料清单查询出所需要的包材数量

            for (Document data : otherOutList) {
                String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
                double instockCount = VtuzxUtil.getDouble(data, "count");//入库的数量
                for (Document bomDoc : materialBomList) {
                    String bomTaskBillNo = VtuzxUtil.getString(bomDoc, "taskBillNo");
                    if (taskBillNo.equals(bomTaskBillNo)) {
                        String childMaterialNo = VtuzxUtil.getString(bomDoc, "childMaterialNo");
                        double numerator = VtuzxUtil.getDouble(bomDoc, "numerator");//分子
                        double denominator = VtuzxUtil.getDouble(bomDoc, "denominator");//分母
                        //所需包材数量为 入库数量 * (分子 / 分母)
                        double count = instockCount * (numerator / denominator);

                        String childMaterialModel = VtuzxUtil.getString(bomDoc, "childMaterialModel");
                        String childMaterialName = VtuzxUtil.getString(bomDoc, "childMaterialName");
                        //即时库存查询是否在库,数量是否够扣,只查询干参包装车间耗材库
                        Document inventoryDoc = inventoryDao.findOne(Criteria.where("materialNo").is(childMaterialNo).and("stockNo").is("035"));
                        if (!VtuzxUtil.isEmpty(inventoryDoc)) {
                            ObjectId _id = VtuzxUtil.getObject(inventoryDoc, "_id");
                            Document inventoryDetailDoc = inventoryDetailDao.findOne(Criteria.where("_inventoryId").is(_id));
                            String boxNo = VtuzxUtil.getString(inventoryDetailDoc, "boxNo");
                            String outLocationNo = VtuzxUtil.getString(inventoryDetailDoc, "locationNo");
                            //说明是在库的
                            if (!VtuzxUtil.isEmpty(inventoryDoc)) {
                                String invStockNo = VtuzxUtil.getString(inventoryDoc, "stockNo");
                                VtuzxMap dataMap = new VtuzxMap();
                                dataMap.append("materialNo", childMaterialNo)
                                        .append("materialName", childMaterialName)
                                        .append("materialModel", childMaterialModel)
                                        .append("boxNo", boxNo)
                                        .append("locationNo", outLocationNo)
                                        .append("count", count)
                                        .append("taskBillNo", taskBillNo)
                                        .append("stockNo", invStockNo);
                                baoCaiList.add(dataMap);
                            } else {
                                _logger.info(String.format("任务单号%s,没有包材库存", taskBillNo));
                            }
                        }

                    }
                }
            }
        }
        //包材做其他出库
        for (VtuzxMap data : baoCaiList) {
            String billNo = IXqcConst.createBillNo(BillType.QTCK);
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String materialName = VtuzxUtil.getString(data, "materialName");
            String materialModel = VtuzxUtil.getString(data, "materialModel");
            String boxNo = VtuzxUtil.getString(data, "boxNo");
            String outStockNo = VtuzxUtil.getString(data, "stockNo");
            String outLocationNo = VtuzxUtil.getString(data, "locationNo");
            String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
            double count = VtuzxUtil.getDouble(data, "count");
            //先添加外层数据
            Document otherOutDoc = new Document();
            otherOutDoc.append("stockNo", outStockNo)
                    .append("boxCount", 1)
                    .append("count", count)
                    .append("type", "无")
                    .append("billNo", billNo)
                    .append("createUserName", name)
                    .append("taskBillNo", taskBillNo)//关联单号
                    .append("remark", "成品出库");
            otherOutDao.insertOne(otherOutDoc);
            //添加内层数据
            Document otherOutDetailDoc = new Document();
            otherOutDetailDoc.append("billNo", billNo)
                    .append("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialSpec", materialModel)
                    .append("batchNo", "*")
                    .append("boxCount", 1)
                    .append("count", count)
                    .append("stockNo", outStockNo);
            ObjectId objectId = otherOutDetailDao.insertOne(otherOutDetailDoc);
            //添加箱号层数据
            Document otherOutBoxDoc = new Document();
            otherOutBoxDoc.append("billNo", billNo)
                    .append("_detailId", objectId)
                    .append("barcodeType", "BC")
                    .append("materialNo", materialNo)
                    .append("boxNo", boxNo)
                    .append("stockNo", outStockNo)
                    .append("locationNo", outLocationNo)
                    .append("count", count);
            otherOutDetailBoxDao.insertOne(otherOutBoxDoc);
            //审核其他出库单
            otherOutService.auditOtherOutOrder(userId, name, outStockNo, billNo);
        }
    }

    /**
     * 生产任务执行报表
     *
     * @param userId
     * @param userName
     * @param param
     * @return
     */
    @Override
    public VtuzxMap getPrdTaskImplList(ObjectId userId, String userName, Map<String, Object> param) {
        String fBillNo = VtuzxUtil.getString(param, "billNo");
        String fMaterialNo = VtuzxUtil.getString(param, "materialNo");
        List<String> fCreateTime = VtuzxUtil.getObject(param, "startTime");
        String fInType = VtuzxUtil.getString(param, "inType");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        Criteria prdCond = new Criteria("task").is(true);//生产任务入库
        if (!VtuzxUtil.isEmpty(fCreateTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(fCreateTime.get(0))).lte(VtuzxUtil.parseDate(fCreateTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(fBillNo)) {
            cond.and("billNo").regex(fBillNo);
        }
        if (!VtuzxUtil.isEmpty(fMaterialNo)) {
            cond.and("materialNo").is(fMaterialNo);
        }
        if (!VtuzxUtil.isEmpty(fInType)) {
            cond.and("inType").is(fInType);
        }
        List<String> billNoList = new ArrayList<>();
        //先从生产任务表中查找任务单号等
        long total = prdTaskDetailDao.countFindPrdTask(cond);//总数量
        Iterator<Document> prdTaskItr = prdTaskDetailDao.findPrdTask(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = new ArrayList<>();
        while (prdTaskItr.hasNext()) {
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            String materialNo = VtuzxUtil.getString(prdTaskDoc, "materialNo");
            String materialName = VtuzxUtil.getString(prdTaskDoc, "materialName");
            String materialModel = VtuzxUtil.getString(prdTaskDoc, "materialModel");//规格
            String unit = VtuzxUtil.getString(prdTaskDoc, "unit");
            double count = VtuzxUtil.getDouble(prdTaskDoc, "count");
            String inType = VtuzxUtil.getString(prdTaskDoc, "inType");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("billNo", billNo)
                    .append("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialSpec", materialModel)
                    .append("unit", unit)
                    .append("count", count)
                    .append("inType", inType)
                    .append("startTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime")));//任务开始时间
            dataList.add(dataMap);
            billNoList.add(billNo);
        }
        //去外层表查询单据状态
        List<VtuzxMap> prdList = new ArrayList<>();
        Iterator<Document> prdItr = prdTaskDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
        while (prdItr.hasNext()) {
            Document prdDoc = prdItr.next();
            VtuzxMap prdMap = new VtuzxMap(prdDoc);
            prdList.add(prdMap);
        }
        //把单据状态放到datalist
        for (VtuzxMap dataMap : dataList) {
            String billNo = VtuzxUtil.getString(dataMap, "billNo");
            for (VtuzxMap prdMap : prdList) {
                String prdBillNo = VtuzxUtil.getString(prdMap, "billNo");
                String status = VtuzxUtil.getString(prdMap, "status");
                if (billNo.equals(prdBillNo)) {
                    dataMap.append("status", status);
                    continue;
                }
            }
        }
        prdCond.and("taskBillNo").in(billNoList);
        List<String> taskList = new ArrayList<>();//存放生产入库编号
        //先查询生产任务入库表里taskBillNo对应的billNo
        Iterator<Document> prdInItr = prdInDao.findList(prdCond, null, 0, 0);
        List<VtuzxMap> prdInList = new ArrayList<>();//存放生产任务入库数据
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
            String billNo = VtuzxUtil.getString(prdInDoc, "billNo");
            Date createTime = VtuzxUtil.getObject(prdInDoc, "createTime");
            double count = VtuzxUtil.getDouble(prdInDoc, "count");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("taskBillNo", taskBillNo)
                    .append("createTime", createTime)
                    .append("count", count)
                    .append("billNo", billNo);
            prdInList.add(dataMap);
            taskList.add(billNo);
        }
        //去生产任务物料级的表里根据billNo找出对应的数据
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(taskList).and("task").is(true), null, 0, 0);
        List<VtuzxMap> prdInDetailList = new ArrayList<>();
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            String batchNo = VtuzxUtil.getString(prdInDetailDoc, "batchNo");
//            double count = VtuzxUtil.getDouble(prdInDetailDoc,"count");
            String billNo = VtuzxUtil.getString(prdInDetailDoc, "billNo");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("batchNo", batchNo)
//                    .append("count",count)
                    .append("billNo", billNo);
            prdInDetailList.add(dataMap);
        }

        //整合生产任务入库表里的数据
        for (VtuzxMap data : prdInList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            for (VtuzxMap detailData : prdInDetailList) {
                String detailBillNo = VtuzxUtil.getString(detailData, "billNo");
                String batchNo = VtuzxUtil.getString(detailData, "batchNo");
//                double count = VtuzxUtil.getDouble(detailData,"count");
                if (billNo.equals(detailBillNo)) {
                    data.append("batchNo", batchNo);
//                            .append("inCount",count);
                }
            }
        }

        //把入库里的数据放到主表里
        for (VtuzxMap data : dataList) {
            double inCounts = 0d;
            String billNo = VtuzxUtil.getString(data, "billNo");
            for (VtuzxMap prdData : prdInList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                String batchNo = VtuzxUtil.getString(prdData, "batchNo");
                double inCount = VtuzxUtil.getDouble(prdData, "count");
                if (billNo.equals(taskBillNo)) {
                    inCounts += inCount;
                    data.append("batchNo", batchNo)
                            .append("endTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdData, "createTime")));
//                        .append("inCount",String.format("%.2f",inCount));
                }
                data.append("inCount", inCounts);
            }
        }
        //计算任务入库数量
//        double inCounts = 0d;
//        for (VtuzxMap data:dataList){
//            String billNo = VtuzxUtil.getString(data,"billNo");
////            double inCount = VtuzxUtil.getDouble(data,"inCount");
//            for (VtuzxMap prdData:prdInList){
//                String taskBillNo = VtuzxUtil.getString(prdData,"taskBillNo");
//                double count = VtuzxUtil.getDouble(prdData,"count");
//                if (billNo.equals(taskBillNo) ){
//                   inCounts +=count;
//                }
//            }
//            data.append("inCount",inCounts);
//        }

        //查询车间收货的数量
        List<String> typeList = new ArrayList<>();
        typeList.add("saveTask");
        typeList.add("prdCol");
        List<VtuzxMap> prdColList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").in(billNoList).and("colType").in(typeList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdCilDoc = prdColItr.next();
            VtuzxMap data = new VtuzxMap(prdCilDoc);
            prdColList.add(data);
        }
        //把车间收货的数量放到主表
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap colMap : prdColList) {
                String taskBillNo = VtuzxUtil.getString(colMap, "taskBillNo");
                double colCount = VtuzxUtil.getDouble(colMap, "count");
                if (billNo.equals(taskBillNo)) {
                    count += colCount;
                    data.append("colCount", count);
                }
            }
        }
        //计算入库状态
        for (VtuzxMap data : dataList) {
            double inCount = VtuzxUtil.getDouble(data, "inCount");
            double count = VtuzxUtil.getDouble(data, "count");
            if (inCount == 0) {
                data.append("inType", "待入库");
            } else if (inCount < count && inCount != 0) {
                data.append("inType", "部分入库");
            } else if (inCount == count) {
                data.append("inType", "已入库");
            } else if (inCount > count) {
                data.append("inType", "超计划入库");
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append(IVtuzxConst.Key_total, total);
    }

    /**
     * 下载生产任务执行报表
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPrdTaskImplList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String fBillNo = VtuzxUtil.getString(param, "billNo");
        String fMaterialNo = VtuzxUtil.getString(param, "materialNo");
        List<String> fCreateTime = VtuzxUtil.getObject(param, "startTime");
        String fInType = VtuzxUtil.getString(param, "inType");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        Criteria prdCond = new Criteria("task").is(true);//生产任务入库
        if (!VtuzxUtil.isEmpty(fCreateTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(fCreateTime.get(0))).lte(VtuzxUtil.parseDate(fCreateTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(fBillNo)) {
            cond.and("billNo").regex(fBillNo);
        }
        if (!VtuzxUtil.isEmpty(fMaterialNo)) {
            cond.and("materialNo").is(fMaterialNo);
        }
        if (!VtuzxUtil.isEmpty(fInType)) {
            cond.and("inType").is(fInType);
        }
        List<String> billNoList = new ArrayList<>();
        //先从生产任务表中查找任务单号等
        long total = prdTaskDetailDao.countFindPrdTask(cond);//总数量
        Iterator<Document> prdTaskItr = prdTaskDetailDao.findPrdTask(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = new ArrayList<>();
        while (prdTaskItr.hasNext()) {
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            String materialNo = VtuzxUtil.getString(prdTaskDoc, "materialNo");
            String materialName = VtuzxUtil.getString(prdTaskDoc, "materialName");
            String materialModel = VtuzxUtil.getString(prdTaskDoc, "materialModel");//规格
            String unit = VtuzxUtil.getString(prdTaskDoc, "unit");
            double count = VtuzxUtil.getDouble(prdTaskDoc, "count");
            String inType = VtuzxUtil.getString(prdTaskDoc, "inType");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("billNo", billNo)
                    .append("materialNo", materialNo)
                    .append("materialName", materialName)
                    .append("materialSpec", materialModel)
                    .append("unit", unit)
                    .append("count", count)
                    .append("inType", inType)
                    .append("startTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdTaskDoc, "createTime")));//任务开始时间
            dataList.add(dataMap);
            billNoList.add(billNo);
        }
        prdCond.and("taskBillNo").in(billNoList);
        List<String> taskList = new ArrayList<>();//存放生产入库编号
        //先查询生产任务入库表里taskBillNo对应的billNo
        Iterator<Document> prdInItr = prdInDao.findList(prdCond, null, 0, 0);
        List<VtuzxMap> prdInList = new ArrayList<>();//存放生产任务入库数据
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String taskBillNo = VtuzxUtil.getString(prdInDoc, "taskBillNo");
            String billNo = VtuzxUtil.getString(prdInDoc, "billNo");
            Date createTime = VtuzxUtil.getObject(prdInDoc, "createTime");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("taskBillNo", taskBillNo)
                    .append("createTime", createTime)
                    .append("billNo", billNo);
            prdInList.add(dataMap);
            taskList.add(billNo);
        }
        //去生产任务物料级的表里根据billNo找出对应的数据
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(taskList), null, 0, 0);
        List<VtuzxMap> prdInDetailList = new ArrayList<>();
        while (prdInDetailItr.hasNext()) {
            Document prdInDetailDoc = prdInDetailItr.next();
            String batchNo = VtuzxUtil.getString(prdInDetailDoc, "batchNo");
            double count = VtuzxUtil.getDouble(prdInDetailDoc, "count");
            String billNo = VtuzxUtil.getString(prdInDetailDoc, "billNo");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("batchNo", batchNo)
                    .append("count", count)
                    .append("billNo", billNo);
            prdInDetailList.add(dataMap);
        }

        //整合生产任务入库表里的数据
        for (VtuzxMap data : prdInList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            for (VtuzxMap detailData : prdInDetailList) {
                String detailBillNo = VtuzxUtil.getString(detailData, "billNo");
                String batchNo = VtuzxUtil.getString(detailData, "batchNo");
                double count = VtuzxUtil.getDouble(detailData, "count");
                if (billNo.equals(detailBillNo)) {
                    data.append("batchNo", batchNo)
                            .append("inCount", count);
                }
            }
        }

        //把入库里的数据放到主表里
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            for (VtuzxMap prdData : prdInList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                String batchNo = VtuzxUtil.getString(prdData, "batchNo");
                double inCount = VtuzxUtil.getDouble(prdData, "inCount");
                if (billNo.equals(taskBillNo)) {
                    data.append("batchNo", batchNo)
                            .append("endTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdData, "createTime")))
                            .append("inCount", inCount);
                }
            }
        }
        //查询车间收货的数量
        List<String> typeList = new ArrayList<>();
        typeList.add("saveTask");
        typeList.add("prdCol");
        List<VtuzxMap> prdColList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").in(billNoList).and("colType").in(typeList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdCilDoc = prdColItr.next();
            VtuzxMap data = new VtuzxMap(prdCilDoc);
            prdColList.add(data);
        }
        //把车间收货的数量放到主表
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap colMap : prdColList) {
                String taskBillNo = VtuzxUtil.getString(colMap, "taskBillNo");
                double colCount = VtuzxUtil.getDouble(colMap, "count");
                if (billNo.equals(taskBillNo)) {
                    count += colCount;
                    data.append("colCount", count);
                }
            }
        }
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "物料台账");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "任务编号"),
                new VtuzxExcelCell(col++, "任务编码"),
                new VtuzxExcelCell(col++, "任务名称"),
                new VtuzxExcelCell(col++, "任务规格"),
                new VtuzxExcelCell(col++, "批次号"),
                new VtuzxExcelCell(col++, "任务单位"),
                new VtuzxExcelCell(col++, "任务数量"),
                new VtuzxExcelCell(col++, "已入库数量"),
                new VtuzxExcelCell(col++, "任务开工时间"),
                new VtuzxExcelCell(col++, "任务入库时间"),
                new VtuzxExcelCell(col++, "入库状态")
        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {
            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "batchNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "unit")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "count")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "inCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "startTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "endTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "inType"))));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 200},
                new int[]{4, 150},
                new int[]{5, 150},
                new int[]{6, 150},
                new int[]{7, 150},
                new int[]{8, 150},
                new int[]{9, 150},
                new int[]{10, 150},
                new int[]{11, 150}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("生产任务执行报表" + timestamp + ".xlsx", stream);
    }

    /**
     * 生产任务审核报表
     *
     * @param userId
     * @param userName
     * @param param
     * @return
     */
    @Override
    public VtuzxMap getPrdTaskAuditList(ObjectId userId, String userName, Map<String, Object> param) {
        String fBillNo = VtuzxUtil.getString(param, "billNo");
        String fProduceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        List<String> fStartTime = VtuzxUtil.getObject(param, "startTime");
        List<String> fCreateTime = VtuzxUtil.getObject(param, "createTime");
        String FType = VtuzxUtil.getString(param, "type");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fBillNo)) {
            cond.and("billNo").regex(fBillNo);
        }
        if (!VtuzxUtil.isEmpty(fProduceHouseName)) {
            cond.and("produceHouseName").regex(fProduceHouseName);
        }
        if (!VtuzxUtil.isEmpty(FType)) {
            cond.and("type").regex(FType);
        }

        if (!VtuzxUtil.isEmpty(fStartTime)) {
            cond.and("startTime").gte(fStartTime.get(0)).lte(fStartTime.get(1) + " 23:59:59");
        }
        if (!VtuzxUtil.isEmpty(fCreateTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(fCreateTime.get(0))).lte(VtuzxUtil.parseDate(fCreateTime.get(1) + " 23:59:59"));
        }

        Criteria returnCond = new Criteria("return").is(true);//退料入库
        Criteria desCond = new Criteria("desalting").is(true);//变品入库
        Criteria taskCond = new Criteria("task").is(true);//领料单入库
        List<VtuzxMap> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();//存放单据号
        long total = prdTaskDao.prdTaskCount(cond);
        Iterator<Document> prdTaskItr = prdTaskDao.prdTaskPage(cond, new Document("createTime", -1), pageIndex, pageSize);
        while (prdTaskItr.hasNext()) {
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            String type = VtuzxUtil.getString(prdTaskDoc, "type");
            String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
            String createUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
            String startTime = VtuzxUtil.getString(prdTaskDoc, "startTime");
            String endTime = VtuzxUtil.getString(prdTaskDoc, "endTime");
            double count = VtuzxUtil.getDouble(prdTaskDoc, "count");
            String status = VtuzxUtil.getString(prdTaskDoc, "status");
            String remark = VtuzxUtil.getString(prdTaskDoc, "remark");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("billNo", billNo)
                    .append("type", type)
                    .append("produceHouseName", produceHouseName)
                    .append("createUserName", createUserName)
                    .append("startTime", startTime)
                    .append("count", count)
                    .append("status", status)
                    .append("endTime", endTime)
                    .append("remark", remark);
            dataList.add(dataMap);
            billNoList.add(billNo);
        }
        //查询领料单领料的数量
        Iterator<Document> prdPickItr = materialBomPickDao.findList(Criteria.where("taskBillNo").in(billNoList).and("status").ne("save"), null, 0, 0);
        List<VtuzxMap> prdPickList = changeList(prdPickItr);

        //退料入库单里的数量
        Iterator<Document> returnItr = prdInDao.findList(returnCond.and("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> returnList = changeList(returnItr);

        //变品退料
        Iterator<Document> desaltingItr = prdInDao.findList(desCond.and("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> desaltingList = changeList(desaltingItr);

        //领料入库
        Iterator<Document> taskItr = prdInDao.findList(taskCond.and("taskBillNo").in(billNoList).and("status").is("audit"), null, 0, 0);
        List<VtuzxMap> taskList = changeList(taskItr);

        //领料单补料
        Iterator<Document> supplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> supplementList = changeList(supplementItr);

        //整理领料单的数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap prdData : prdPickList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                double pickCount = VtuzxUtil.getDouble(prdData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + pickCount;
                    data.append("pickCount", count);
                }
            }
        }
        //整理退料入库数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap prdData : returnList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                double returnCount = VtuzxUtil.getDouble(prdData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + returnCount;
                    data.append("returnCount", count);
                }
            }
        }

        //整理变品入库数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap desData : desaltingList) {
                String taskBillNo = VtuzxUtil.getString(desData, "taskBillNo");
                double desCount = VtuzxUtil.getDouble(desData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + desCount;
                    data.append("desCount", count);
                }
            }
        }
        //整理领料入库数量dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap taskData : taskList) {
                String taskBillNo = VtuzxUtil.getString(taskData, "taskBillNo");
                double taskCount = VtuzxUtil.getDouble(taskData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + taskCount;
                    data.append("taskCount", count);
                }
            }
        }
        //整理生产补料入库数量dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap taskData : supplementList) {
                String taskBillNo = VtuzxUtil.getString(taskData, "taskBillNo");
                double taskCount = VtuzxUtil.getDouble(taskData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + taskCount;
                    data.append("supCount", count);
                }
            }
        }

        //查询车间收货退货的数量
        List<VtuzxMap> prdColList = new ArrayList<>();
        Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").in(billNoList), null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdCilDoc = prdColItr.next();
            VtuzxMap data = new VtuzxMap(prdCilDoc);
            prdColList.add(data);
        }
        //把车间收货退货的数量放到主表
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;           //退料数量
            double desCount = 0;        //变品数量
            double savePrdCount = 0;   //任务收货和车间收货数量
            for (VtuzxMap colMap : prdColList) {
                String taskBillNo = VtuzxUtil.getString(colMap, "taskBillNo");
                String colType = VtuzxUtil.getString(colMap, "colType");
                if (colType.equals("return") && billNo.equals(taskBillNo)) {//退料数量
                    double returnCount = VtuzxUtil.getDouble(colMap, "count");
                    count += returnCount;
                    data.append("colReturnCount", count);
                }
                if (colType.equals("desaltingIn") && billNo.equals(taskBillNo)) {//变品数量
                    double dCount = VtuzxUtil.getDouble(colMap, "count");
                    desCount += dCount;
                    data.append("colDesCount", desCount);
                }
                if (((colType.equals("saveTask") || colType.equals("prdCol")) && billNo.equals(taskBillNo))) {
                    double prdCount = VtuzxUtil.getDouble(colMap, "count");
                    savePrdCount += prdCount;
                    data.append("savePrdCount", savePrdCount);
                }
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append(IVtuzxConst.Key_total, total);
    }

    /**
     * 下载生产任务审核报表
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPrdTaskAuditList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String fBillNo = VtuzxUtil.getString(param, "billNo");
        String fProduceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        List<String> fStartTime = VtuzxUtil.getObject(param, "startTime");
        List<String> fCreateTime = VtuzxUtil.getObject(param, "createTime");
        String FType = VtuzxUtil.getString(param, "type");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fBillNo)) {
            cond.and("billNo").regex(fBillNo);
        }
        if (!VtuzxUtil.isEmpty(fProduceHouseName)) {
            cond.and("produceHouseName").regex(fProduceHouseName);
        }
        if (!VtuzxUtil.isEmpty(FType)) {
            cond.and("type").regex(FType);
        }

        if (!VtuzxUtil.isEmpty(fStartTime)) {
            cond.and("startTime").gte(fStartTime.get(0)).lte(fStartTime.get(1) + " 23:59:59");
        }
        if (!VtuzxUtil.isEmpty(fCreateTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(fCreateTime.get(0))).lte(VtuzxUtil.parseDate(fCreateTime.get(1) + " 23:59:59"));
        }

        Criteria returnCond = new Criteria("return").is(true);//退料入库
        Criteria desCond = new Criteria("desalting").is(true);//变品入库
        Criteria taskCond = new Criteria("task").is(true);//领料单入库
        List<VtuzxMap> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();//存放单据号
        long total = prdTaskDao.prdTaskCount(cond);
        Iterator<Document> prdTaskItr = prdTaskDao.prdTaskPage(cond, new Document("createTime", -1), pageIndex, pageSize);
        while (prdTaskItr.hasNext()) {
            Document prdTaskDoc = prdTaskItr.next();
            String billNo = VtuzxUtil.getString(prdTaskDoc, "billNo");
            String type = VtuzxUtil.getString(prdTaskDoc, "type");
            String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
            String createUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
            String startTime = VtuzxUtil.getString(prdTaskDoc, "startTime");
            String endTime = VtuzxUtil.getString(prdTaskDoc, "endTime");
            double count = VtuzxUtil.getDouble(prdTaskDoc, "count");
            String status = VtuzxUtil.getString(prdTaskDoc, "status");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("billNo", billNo)
                    .append("type", type)
                    .append("produceHouseName", produceHouseName)
                    .append("createUserName", createUserName)
                    .append("startTime", startTime)
                    .append("count", count)
                    .append("status", status)
                    .append("endTime", endTime);
            dataList.add(dataMap);
            billNoList.add(billNo);
        }
        //查询领料单领料的数量
        Iterator<Document> prdPickItr = materialBomPickDao.findList(Criteria.where("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> prdPickList = changeList(prdPickItr);

        //退料入库单里的数量
        Iterator<Document> returnItr = prdInDao.findList(returnCond.and("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> returnList = changeList(returnItr);

        //变品退料
        Iterator<Document> desaltingItr = prdInDao.findList(desCond.and("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> desaltingList = changeList(desaltingItr);

        //领料入库
        Iterator<Document> taskItr = prdInDao.findList(taskCond.and("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> taskList = changeList(taskItr);

        //领料单补料
        Iterator<Document> supplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").in(billNoList), null, 0, 0);
        List<VtuzxMap> supplementList = changeList(supplementItr);

        //整理领料单的数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap prdData : prdPickList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                double pickCount = VtuzxUtil.getDouble(prdData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + pickCount;
                    data.append("pickCount", String.format("%.2f", count));
                }
            }
        }
        //整理退料入库数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap prdData : returnList) {
                String taskBillNo = VtuzxUtil.getString(prdData, "taskBillNo");
                double returnCount = VtuzxUtil.getDouble(prdData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + returnCount;
                    data.append("returnCount", String.format("%.2f", count));
                }
            }
        }

        //整理变品入库数量到dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap desData : desaltingList) {
                String taskBillNo = VtuzxUtil.getString(desData, "taskBillNo");
                double desCount = VtuzxUtil.getDouble(desData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + desCount;
                    data.append("desCount", String.format("%.2f", count));
                }
            }
        }
        //整理领料入库数量dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap taskData : taskList) {
                String taskBillNo = VtuzxUtil.getString(taskData, "taskBillNo");
                double taskCount = VtuzxUtil.getDouble(taskData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + taskCount;
                    data.append("taskCount", String.format("%.2f", count));
                }
            }
        }
        //整理生产补料入库数量dataList
        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            double count = 0;
            for (VtuzxMap taskData : supplementList) {
                String taskBillNo = VtuzxUtil.getString(taskData, "taskBillNo");
                double taskCount = VtuzxUtil.getDouble(taskData, "count");
                if (billNo.equals(taskBillNo)) {
                    count = count + taskCount;
                    data.append("supCount", String.format("%.2f", count));
                }
            }
        }
        //修改单据状态
        for (VtuzxMap data : dataList) {
            String status = VtuzxUtil.getString(data, "status");
            if (status.equals("audit")) {
                data.replace("status", "审核");
            } else if (status.equals("save")) {
                data.replace("status", "保存");
            } else if (status.equals("close")) {
                data.replace("status", "关闭");
            }
        }
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "物料台账");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "状态"),
                new VtuzxExcelCell(col++, "单据编码"),
                new VtuzxExcelCell(col++, "单据类型"),
                new VtuzxExcelCell(col++, "生产车间"),
                new VtuzxExcelCell(col++, "创建人"),
                new VtuzxExcelCell(col++, "开工时间"),
                new VtuzxExcelCell(col++, "数量"),
                new VtuzxExcelCell(col++, "领料单领料"),
                new VtuzxExcelCell(col++, "领料单补料"),
                new VtuzxExcelCell(col++, "退料入库单"),
                new VtuzxExcelCell(col++, "变品退料"),
                new VtuzxExcelCell(col++, "领料单入库"),
                new VtuzxExcelCell(col++, "完工时间")


        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "status")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "startTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "count")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "pickCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "supCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "returnCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "desCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "taskCount")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "endTime"))
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 200},
                new int[]{4, 150},
                new int[]{5, 150},
                new int[]{6, 150},
                new int[]{7, 150},
                new int[]{8, 150},
                new int[]{9, 150},
                new int[]{10, 150},
                new int[]{11, 150},
                new int[]{12, 150}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("生产任务审核" + timestamp + ".xlsx", stream);
    }

    /**
     * 用于getPrdTaskAuditList
     *
     * @param innerItr
     * @return
     */
    @Override
    public List<VtuzxMap> changeList(Iterator<Document> innerItr) {
        List<VtuzxMap> innerList = new ArrayList<>();
        while (innerItr.hasNext()) {
            Document innerDoc = innerItr.next();
            double count = VtuzxUtil.getDouble(innerDoc, "count");
            String taskBillNo = VtuzxUtil.getString(innerDoc, "taskBillNo");
            VtuzxMap dataMap = new VtuzxMap();
            dataMap.append("count", count)
                    .append("taskBillNo", taskBillNo);
            innerList.add(dataMap);
        }
        return innerList;
    }

    /**
     * 生产任务审核详情页面
     *
     * @param userId
     * @param billNo
     * @return
     */
    @Override
    public VtuzxMap getProduceTaskAuditDetail(ObjectId userId, String billNo) {
        Criteria returnCond = new Criteria("return").is(true);//退料入库
        Criteria desCond = new Criteria("desalting").is(true);//变品入库
        Criteria taskCond = new Criteria("task").is(true);//领料单入库
        //头数据
        Document prdTaskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(billNo));
        String prdBillNo = VtuzxUtil.getString(prdTaskDetailDoc, "billNo");
        String materialName = VtuzxUtil.getString(prdTaskDetailDoc, "materialName");
        String materialModel = VtuzxUtil.getString(prdTaskDetailDoc, "materialModel");
        String materialNo = VtuzxUtil.getString(prdTaskDetailDoc, "materialNo");
        String unit = VtuzxUtil.getString(prdTaskDetailDoc, "unit");
        double count = VtuzxUtil.getDouble(prdTaskDetailDoc, "count");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String status = VtuzxUtil.getString(prdTaskDoc, "status");
        String auditUserName = VtuzxUtil.getString(prdTaskDoc, "auditUserName");
        VtuzxMap header = new VtuzxMap("billNo", prdBillNo)
                .append("materialName", materialName)
                .append("materialModel", materialModel)
                .append("unit", unit)
                .append("count", count)
                .append("materialNo", materialNo)
                .append("status", status)
                .append("auditUserName", auditUserName);
        //领料单领料里的数据
        List<VtuzxMap> pickList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        //先查询dao里的数据
        Iterator<Document> pickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        while (pickItr.hasNext()) {
            Document pickDoc = pickItr.next();
            String pickBillNo = VtuzxUtil.getString(pickDoc, "billNo");
            VtuzxMap dataMap = new VtuzxMap(pickDoc);
            billNoList.add(pickBillNo);
            pickList.add(dataMap);
        }

        //领料补料
        List<VtuzxMap> supList = new ArrayList<>();
        Iterator<Document> supItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
        while (supItr.hasNext()) {
            Document supDoc = supItr.next();
            VtuzxMap dataMap = new VtuzxMap(supDoc);
            supList.add(dataMap);
        }
//
        //领料单入库
        Iterator<Document> taskItr = prdInDao.findList(taskCond.and("taskBillNo").is(billNo), null, 0, 0);
        List<VtuzxMap> taskList = getAuditList(taskItr, billNo, taskCond);

        //退料入库
        Iterator<Document> returnDetailItr = prdInDao.findList(returnCond.and("taskBillNo").is(billNo), null, 0, 0);
        List<VtuzxMap> returnList = getAuditList(returnDetailItr, billNo, returnCond);

        //变品退料入库
        Iterator<Document> desDetailItr = prdInDao.findList(desCond.and("taskBillNo").is(billNo), null, 0, 0);
        List<VtuzxMap> desList = getAuditList(desDetailItr, billNo, desCond);

        return new VtuzxMap("header", header).append("pickList", pickList).append("taskList", taskList).append("returnList", returnList).append("desList", desList).append("supList", supList);

    }

    /**
     * 用于生产任务审核详情
     *
     * @param innerItr
     * @return
     */
    @Override
    public List<VtuzxMap> getAuditList(Iterator<Document> innerItr, String taskBillNo, Criteria cond) {
        List<VtuzxMap> dataList = new ArrayList<>();
        if (innerItr.hasNext()) {//如果不止一条
            List<String> billNoList = new ArrayList<>();
            while (innerItr.hasNext()) {
                Document innerDoc = innerItr.next();
                String billNo = VtuzxUtil.getString(innerDoc, "billNo");
                billNoList.add(billNo);
            }
            //去详情表里查询信息、
            Iterator<Document> detailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detailDoc = detailItr.next();
                VtuzxMap dataMap = new VtuzxMap(detailDoc);
                dataList.add(dataMap);
            }
        } else {//如果只有一条
            Document innerDoc = prdInDao.findOne(cond);
            String tBillNo = "";
            if (!VtuzxUtil.isEmpty(innerDoc)) {
                tBillNo = VtuzxUtil.getString(innerDoc, "billNo");
                Iterator<Document> detailItr = prdInDetailDao.findList(Criteria.where("billNo").is(tBillNo), null, 0, 0);
                while (detailItr.hasNext()) {
                    Document detailDoc = detailItr.next();
                    VtuzxMap dataMap = new VtuzxMap(detailDoc);
                    dataList.add(dataMap);
                }
            }
        }
        return dataList;
    }

    /**
     * 修改生产任务备注
     *
     * @param _userId  用户ID
     * @param userName 用户名
     * @param param
     * @return
     * @throws VtuzxException
     */
    @Override
    public VtuzxMap saveProTaskBill(ObjectId _userId, String userName, Map<String, Object> param) throws VtuzxException {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String remark = VtuzxUtil.getString(param, "remark");
        Criteria cond = new Criteria("billNo").is(billNo);
        Document prdTaskDoc = prdTaskDao.findOne(cond);
        String businessStatus = VtuzxUtil.getString(prdTaskDoc, "businessStatus");
        if (businessStatus.equals("end")) {
            throw new VtuzxException("任务以完工,无法修改");
        }
        prdTaskDoc.replace("remark", remark);
//        prdTaskDoc.append("_updateUserId",_userId)
//                .append("_updateUserName",userName)
//                .append("remark",remark);
        prdTaskDao.updateOne(cond, prdTaskDoc);
        return new VtuzxMap("billNo", billNo);
    }

    /**
     * 获取车间收货部分信息（边，董，潘）
     *
     * @param userId
     * @param param
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public VtuzxMap getPrdColPartBill(ObjectId userId, Map<String, Object> param, int pageIndex, int pageSize) {
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String materialName = VtuzxUtil.getString(param, "materialName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        String colBillNo = VtuzxUtil.getString(param, "billNo");
        String isNoStockIn = VtuzxUtil.getString(param, "isNoStockIn");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(materialNo)) {
            cond.and("materialNo").regex(materialNo);
        }
        if (!VtuzxUtil.isEmpty(materialName)) {
            cond.and("materialName").regex("^.*" + materialName + ".*$");
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        Criteria detailCond = new Criteria();
        Criteria taskCond = new Criteria();//任务表查询条件
        detailCond.and("inStock").ne(true);
        if (VtuzxUtil.isEmpty(createTime)) {//查询时间过长给一个默认时间
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, -2);
            Date proviceDate = calendar.getTime();
            detailCond.and("createTime").gte(proviceDate).lte(new Date());
            taskCond.and("createTime").gte(proviceDate).lte(new Date());
        } else {
            detailCond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
            taskCond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }

        if (!VtuzxUtil.isEmpty(colBillNo)) {
            cond.and("billNo").regex(colBillNo);
            detailCond.and("billNo").regex(colBillNo);
        }
        List<String> notInStockBillNoList = new ArrayList<>();//还没入库的入库号集合
        Iterator<Document> colDetailItr = prdColDetailDao.findList(detailCond, null, 0, 0);
        while (colDetailItr.hasNext()) {
            Document colDetail = colDetailItr.next();
            String notInStockBillNo = VtuzxUtil.getString(colDetail, "billNo");
            if (!notInStockBillNoList.contains(notInStockBillNo)) {
                notInStockBillNoList.add(notInStockBillNo);
            }
        }
        if (VtuzxUtil.isEmpty(colBillNo)) {
            if (!VtuzxUtil.isEmpty(isNoStockIn)) {
                if (Boolean.parseBoolean(isNoStockIn)) {
                    cond.and("billNo").nin(notInStockBillNoList);
                } else {
                    cond.and("billNo").in(notInStockBillNoList);
                }
            }
        }
        List<String> nameList = new ArrayList<>();
        nameList.add("边超境");
        nameList.add("董颖");
        nameList.add("潘振霞");
        nameList.add("董颖2");
        nameList.add("张辉");
        nameList.add("张辉1");
        nameList.add("张辉2");
        nameList.add("都辉辉");
        nameList.add("都辉辉1");
        nameList.add("都辉辉2");

//        List<String> produceList = new ArrayList<>();
//        produceList.add("冻品参车间");
//        produceList.add("外包装车间1");
//        produceList.add("干参包装车间");
//        List<String> taskBillNoList = new ArrayList<>();
//        Iterator<Document> prdTakItr =  prdTaskDao.findList(taskCond.and("produceHouseName").in(produceList),new Document("createTime",-1),0,0);
//        while (prdTakItr.hasNext()){
//            Document prdTaskDoc = prdTakItr.next();
//            String taskBillNo = VtuzxUtil.getString(prdTaskDoc,"billNo");
//            if (!taskBillNoList.contains(taskBillNo)){
//                taskBillNoList.add(taskBillNo);
//            }
//
//        }
//        //改成根据车间查询
        VtuzxPage page = prdColDao.page(cond.and("createUserName").in(nameList), new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("materialNo", VtuzxUtil.getString(doc, "materialNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("materialName", VtuzxUtil.getObject(doc, "materialName"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));

        for (VtuzxMap data : dataList) {
            String billNo = VtuzxUtil.getString(data, "billNo");
            if (notInStockBillNoList.contains(billNo)) {//还没入库
                data.append("isNoStockIn", false);
            } else {
                data.append("isNoStockIn", true);
            }
        }
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxDownloadBean downloadPrdColPartBill(VtuzxToken token, Map<String, Object> param) throws Exception {
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String materialName = VtuzxUtil.getString(param, "materialName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(materialNo)) {
            cond.and("materialNo").regex(materialNo);
        }
        if (!VtuzxUtil.isEmpty(materialName)) {
            cond.and("materialName").regex("^.*" + materialName + ".*$");
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        List<String> nameList = new ArrayList<>();
        nameList.add("边超境");
        nameList.add("董颖");
        nameList.add("潘振霞");
        nameList.add("董颖2");
        nameList.add("张辉");
        nameList.add("张辉1");
        nameList.add("张辉2");
        VtuzxPage page = prdColDao.page(cond.and("createUserName").in(nameList), new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("materialNo", VtuzxUtil.getString(doc, "materialNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("materialName", VtuzxUtil.getObject(doc, "materialName"))
                .append("count", VtuzxUtil.getDouble(doc, "count"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));

        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "物料台账");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "物料编号"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "总重量"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col++, "创建人")

        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "count")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName"))
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 200},
                new int[]{4, 150}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
//        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("车间收货(库管)" + timestamp + ".xlsx", stream);
    }

    //修改车间收货是否打印
    @Override
    public VtuzxMap updatePrdColSeal(ObjectId userId, String name, Map<String, Object> param) {
        String billNoList = VtuzxUtil.getString(param, "billNoList");
        String[] splitList = billNoList.split(",");
        Criteria cond = Criteria.where("billNo").in(splitList);
        Iterator<Document> prdColItr = prdColDao.findList(cond, null, 0, 0);
        while (prdColItr.hasNext()) {
            Document prdColDoc = prdColItr.next();
            String _id = VtuzxUtil.getString(prdColDoc, "_id");
//            prdColDoc.replace("isPrint","seal");
//            prdColDoc.append("printUserName",name)
//                    .append("printUserId",userId)
//                    .append("printTime",new Date());
            prdColDao.updateById(_id, new Document("isPrint", "seal")
                    .append("printUserName", name)
                    .append("printUserId", userId)
                    .append("printTime", new Date()));
        }
        return new VtuzxMap("isPrint", billNoList);
    }

    //修改生产领料单是否打印
    @Override
    public VtuzxMap updateMaterialSeal(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document materialDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String _id = VtuzxUtil.getString(materialDoc, "_id");
//        materialDoc.replace("isPrint","seal");
        materialBomPickDao.updateById(_id, new Document("isPrint", "seal"));
        return new VtuzxMap("isPrint", billNo);
    }

    @Override
    public VtuzxMap updateSupplementSeal(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document materialDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
        String _id = VtuzxUtil.getString(materialDoc, "_id");
        materialBomSupplementDao.updateById(_id, new Document("isPrint", "seal"));
        return new VtuzxMap("isPrint", billNo);
    }

    @Override
    public VtuzxMap updatePrdTaskSeal(ObjectId userId, String name, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String _id = VtuzxUtil.getString(prdTaskDoc, "_id");
        prdTaskDao.updateById(_id, new Document("isPrint", "seal"));
        return new VtuzxMap("isPrint", billNo);
    }

    @Override
    public VtuzxMap addPrdColAndGetPrdCol(ObjectId userId, String name, Map<String, Object> param) throws VtuzxException, InterruptedException {
        String serialNo = VtuzxUtil.getString(param, "serialNo");//当前追溯
        Map<String, Object> currentBox = VtuzxUtil.getObject(param, "currentBox");//当前箱
        List<String> traceBackList = VtuzxUtil.getObject(currentBox, "traceBack");
        int index = VtuzxUtil.getInt(param, "index");//当前索引 用来排序
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        if (VtuzxUtil.isEmpty(serialNo)) {
            throw new VtuzxException("追溯码为空");
        }

        // 存在校验
        {
            long count = traceabilityCodeDetailDao.count(Criteria.where("traceabilityCode").is(serialNo).and("enableStatus").is(false));
            if (count <= 0) {
                throw new VtuzxException("追溯码不存在");
            }
        }
        //判断追溯是否重复
        Document prdColDetailDoc = prdColDetailDao.findOne(Criteria.where("traceBack").in(serialNo));
        if (!VtuzxUtil.isEmpty(prdColDetailDoc)) {
            throw new VtuzxException("追溯码重复");
        }
        if (traceBackList.contains(serialNo)) {
            throw new VtuzxException("追溯码重复");
        }


        Document prdTskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseName = VtuzxUtil.getString(prdTskDoc, "produceHouseName");
        int standard = VtuzxUtil.getInt(currentBox, "standard");
        if (VtuzxUtil.isEmpty(standard)) {
            throw new VtuzxException("有箱子被删除请刷新一下");
        }
        List<String> traceBack = VtuzxUtil.getObject(currentBox, "traceBack");
        Map<String, Object> getParam = new HashMap<>();
        getParam.put("taskBillNo", taskBillNo);

        VtuzxMap dataMap = new VtuzxMap();//返给前端的数据
        //判断是否需要新增箱子,新增箱子后直接返回新增的数据，
        if (traceBack.size() == standard) {//追溯数量和标准数量相等，需要新增箱子
            VtuzxMap currentMap = addNewBox(userId, name, currentBox, serialNo, index, taskBillNo, produceHouseName);//返回新的箱子
            //返给前端
            List<VtuzxMap> dataList = new ArrayList<>();
            Iterator<Document> detailItr = prdColDetailDao.findList(Criteria.where("isTemp").is(true).and("taskBillNo").is(taskBillNo), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detailDoc = detailItr.next();
                VtuzxMap data = new VtuzxMap(detailDoc);
                data.append("_insertUserId", VtuzxUtil.removeString(dataMap, "_insertUserId"));
                data.append("id", VtuzxUtil.removeString(data, "_id"));
                dataList.add(data);
            }
            //重新计算索引(查询当前任务箱码数量，新增的话新增到最后一箱)
            Long newIndex = prdColDetailDao.count(Criteria.where("isTemp").is(true).and("taskBillNo").is(taskBillNo));
            dataMap.append("dataList", dataList)
                    .append("item", currentMap)
                    .append("index", newIndex - 1);
            _logger.info(String.format("唯一码%s,最后返回的索引为%d", serialNo, newIndex - 1));
            System.out.println(String.format("唯一码%s,最后返回的索引为%d", serialNo, newIndex - 1));
            return dataMap;
        }

        //如果不是新增的箱子
        if (!produceHouseName.equals("干参包装车间")) {//如果不是干参包装车间每次都重新排序
            double count = 0;
            boolean flag = false;//如果是最后一个追溯，修改打印状态
            String id = VtuzxUtil.getString(currentBox, "id");
            String materialNo = VtuzxUtil.getString(currentBox, "materialNo");
            String materialName = VtuzxUtil.getString(currentBox, "materialName");
            String materialModel = VtuzxUtil.getString(currentBox, "materialModel");
            String supplierNo = VtuzxUtil.getString(currentBox, "supplierNo");
            String supplierName = VtuzxUtil.getString(currentBox, "supplierName");
//            int standard = VtuzxUtil.getInt(currentBox, "standard");
            int currentCount = VtuzxUtil.getInt(currentBox, "currentCount");
            boolean isDelete = VtuzxUtil.getBoolean(currentBox, "isDelete");
            String billNo = VtuzxUtil.getString(currentBox, "billNo");
            String unit = VtuzxUtil.getString(currentBox, "unit");
            String unitName = VtuzxUtil.getString(currentBox, "unitName");
            String department = VtuzxUtil.getString(currentBox, "department");
            String batchNo = VtuzxUtil.getString(currentBox, "batchNo");
            double sumCount = VtuzxUtil.getDouble(currentBox, "count");

            double traceCount = VtuzxUtil.getDouble(currentBox, "traceCount");//追溯重量
//            List<String> traceBack = VtuzxUtil.getObject(currentBox, "traceBack");
            if (traceBack.size() < standard && !VtuzxUtil.isEmpty(serialNo)) {
                traceBack.add(serialNo);//添加最后一次扫码信息
            }
            if (traceBack.size() == standard) {
                flag = true;
            }
            currentCount = traceBack.size();//已扫数量等于追溯数量
            sumCount = currentCount;
            if (traceCount == 1 || traceCount == 0) {
                count = sumCount;
            } else {
                count = traceBack.size() * traceCount;
            }
            String oldBoxNo = VtuzxUtil.getString(currentBox, "boxNo");
            int order = index + 1;
            Thread.sleep(10);
            String boxNo = "A02" + new Date().getTime();
            Document updateDoc = new Document("materialNo", materialNo)
                    .append("materialModel", materialModel)
                    .append("materialName", materialName)
                    .append("supplierNo", supplierNo)
                    .append("supplierName", supplierName)
                    .append("unit", unit)
                    .append("unitName", unitName)
//                    .append("boxNo",boxNo)
                    .append("batchNo", batchNo)
                    .append("count", count * 100 / 100)
                    .append("inStock", false)
                    .append("comment", "")
                    .append("_insertUserId", userId)
                    .append("insertUserName", name)
                    .append("isTemp", true)
                    .append("noPrint", true)
                    .append("taskBillNo", taskBillNo)
                    .append("department", department)
                    .append("standard", standard)
                    .append("isDelete", isDelete)
                    .append("currentCount", currentCount)
                    .append("traceCount", traceCount)
                    .append("orderNum", String.format("%04d", order))
                    .append("traceBack", traceBack);
            if (VtuzxUtil.isEmpty(oldBoxNo)) {
                updateDoc.append("boxNo", boxNo);
            }
            if (VtuzxUtil.isEmpty(id)) {
                prdColDetailDao.insertOne(updateDoc);
            } else {
                if (!flag) {
                    updateDoc.remove("noPrint");
                }
                prdColDetailDao.updateById(id, updateDoc);
            }

            //返给前端
            List<VtuzxMap> dataList = new ArrayList<>();
            Iterator<Document> detailItr = prdColDetailDao.findList(Criteria.where("isTemp").is(true).and("taskBillNo").is(taskBillNo), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detailDoc = detailItr.next();
                VtuzxMap data = new VtuzxMap(detailDoc);
                data.append("_insertUserId", VtuzxUtil.removeString(dataMap, "_insertUserId"));
                data.append("id", VtuzxUtil.removeString(data, "_id"));
                dataList.add(data);
            }
            dataMap.append("dataList", dataList)
                    .append("item", new VtuzxMap(updateDoc))
                    .append("index", index);
        } else {//否则按照之前收货的数量继续排序
            double count = 0;
            String id = VtuzxUtil.getString(currentBox, "id");
            String materialNo = VtuzxUtil.getString(currentBox, "materialNo");
            String materialName = VtuzxUtil.getString(currentBox, "materialName");
            String materialModel = VtuzxUtil.getString(currentBox, "materialModel");
            String supplierNo = VtuzxUtil.getString(currentBox, "supplierNo");
            String supplierName = VtuzxUtil.getString(currentBox, "supplierName");
//            int standard = VtuzxUtil.getInt(box, "standard");
            int currentCount = VtuzxUtil.getInt(currentBox, "currentCount");
            boolean isDelete = VtuzxUtil.getBoolean(currentBox, "isDelete");
//            String billNo = VtuzxUtil.getString(currentBox, "billNo");
            String unit = VtuzxUtil.getString(currentBox, "unit");
            String unitName = VtuzxUtil.getString(currentBox, "unitName");
            String department = VtuzxUtil.getString(currentBox, "department");
            String batchNo = VtuzxUtil.getString(currentBox, "batchNo");
            double sumCount = VtuzxUtil.getDouble(currentBox, "count");
//            int orderNum = VtuzxUtil.getInt(currentBox, "orderNum");//排序序号

            double traceCount = VtuzxUtil.getDouble(currentBox, "traceCount");//追溯重量
//            List<String> traceBack = VtuzxUtil.getObject(currentBox, "traceBack");
            if (traceBack.size() < standard && !VtuzxUtil.isEmpty(serialNo)) {
                traceBack.add(serialNo);//添加最后一次扫码信息

            }
            currentCount = traceBack.size();//已扫数量
            sumCount = currentCount;
            if (traceCount == 1 || traceCount == 0) {
                count = sumCount;
            } else {
                count = traceBack.size() * traceCount;
            }

            String oldBoxNo = VtuzxUtil.getString(currentBox, "boxNo");
            double orderCount = prdColDetailDao.count(Criteria.where("taskBillNo").is(taskBillNo).and("isTemp").ne(true));//查询之前入库数

            int order = (int) (orderCount + index + 1);
            Thread.sleep(10);
            long time = new Date().getTime();
            String boxNo = "A02" + time;
            Document updateDoc = new Document("materialNo", materialNo)
                    .append("materialModel", materialModel)
                    .append("materialName", materialName)
                    .append("supplierNo", supplierNo)
                    .append("supplierName", supplierName)
                    .append("unit", unit)
                    .append("unitName", unitName)
//                    .append("boxNo", boxNo)
                    .append("batchNo", batchNo)
                    .append("count", count * 100 / 100)
                    .append("inStock", false)
                    .append("comment", "")
                    .append("_insertUserId", userId)
                    .append("insertUserName", name)
                    .append("isTemp", true)
                    .append("noPrint", true)
                    .append("taskBillNo", taskBillNo)
                    .append("department", department)
                    .append("standard", standard)
                    .append("isDelete", isDelete)
                    .append("currentCount", currentCount)
                    .append("traceCount", traceCount)
                    .append("orderNum", String.format("%04d", order))
                    .append("traceBack", traceBack);
            if (VtuzxUtil.isEmpty(oldBoxNo)) {
                updateDoc.append("boxNo", boxNo);
            }
            if (VtuzxUtil.isEmpty(id)) {
                prdColDetailDao.insertOne(updateDoc);
            } else {
                updateDoc.remove("noPrint");
                prdColDetailDao.updateById(id, updateDoc);
            }
            //返给前端
            List<VtuzxMap> dataList = new ArrayList<>();
            Iterator<Document> detailItr = prdColDetailDao.findList(Criteria.where("isTemp").is(true).and("taskBillNo").is(taskBillNo), null, 0, 0);
            while (detailItr.hasNext()) {
                Document detailDoc = detailItr.next();
                VtuzxMap data = new VtuzxMap(detailDoc);
                data.append("_insertUserId", VtuzxUtil.removeString(dataMap, "_insertUserId"));
                data.append("id", VtuzxUtil.removeString(data, "_id"));
                dataList.add(data);
            }
            dataMap.append("dataList", dataList)
                    .append("item", new VtuzxMap(updateDoc))
                    .append("index", index);

        }
        _logger.info(String.format("唯一码%s,最后返回的索引为%d", serialNo, index));
        System.out.println(String.format("唯一码%s,最后返回的索引为%d", serialNo, index));
        return dataMap;
    }

    @Override
    public VtuzxMap syncKingdeeReturn(ObjectId userId, String name, List<String> billNoList) throws Exception {
        for (String billNo : billNoList) {
            try {
                syncKingdeeOrderService.syncReturn(userId, name, billNo, "hand", null);
            } catch (Exception e) {
                _logger.info(e.getMessage());
                throw new VtuzxException(e.getMessage());
            }
            //修改传单状态
            UpdateResult res = prdInDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("isUpload", "yes")));
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
        }

        return null;
    }

    @Override
    public VtuzxMap syncKingdeeDesalting(ObjectId userId, String userName, List<Map<String, Object>> billNoList) throws Exception {

        for (Map<String, Object> map : billNoList) {
            String billNo = VtuzxUtil.getString(map, "billNo");
            String taskBillNo = VtuzxUtil.getString(map, "taskBillNo");
            try {
                syncKingdeeOrderService.syncDesaltingInStock(userId, userName, taskBillNo, billNo, "hand", null, 0);
            } catch (Exception e) {
                _logger.info(e.getMessage());
                throw new VtuzxException(e.getMessage());
            }
            //修改传单状态
            UpdateResult res = prdInDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("isUpload", "yes")));
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
        }

        return null;
    }

    @Override
    public VtuzxMap syncKingdeeInStock(ObjectId userId, String userName, List<String> billNoList) throws Exception {
        for (String billNo : billNoList) {
            try {
                syncKingdeeOrderService.syncPrdInStockOrder(userId, userName, billNo, "hand", null);
            } catch (Exception e) {
                _logger.info(e.getMessage());
                throw new VtuzxException(e.getMessage());
            }
            //修改传单状态
            UpdateResult res = prdInDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("isUpload", "yes")));
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
        }
        return null;
    }

    //手动传单
    @Override
    public VtuzxMap uploadKingdeeTask(ObjectId userId, String userName, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskTime = VtuzxUtil.getString(param, "taskTime");//订单日期
        String createTime = VtuzxUtil.getString(param, "createTime");//订单创建时间
        String subTime = createTime.substring(0, 10);
        Boolean checked = VtuzxUtil.getBoolean(param, "checked");//是否只传调拨单(分选)

        String pickTime = VtuzxUtil.getString(param, "pickTime");//领料日期
        //跨月问题修改订单的日期，如果领料没传默认为订单日期
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(pickTime)) {
            pickTime = taskTime;
        }
        String supplementTime = VtuzxUtil.getString(param, "supplementTime");//补料
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(supplementTime)) {
            supplementTime = taskTime;
        }
        String returnTime = VtuzxUtil.getString(param, "returnTime");//退料
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(returnTime)) {
            returnTime = taskTime;
        }
        String desaltingTime = VtuzxUtil.getString(param, "desaltingTime");//变品退料
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(desaltingTime)) {
            desaltingTime = taskTime;
        }
        String prdInTime = VtuzxUtil.getString(param, "prdInTime");//入库
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(prdInTime)) {
            prdInTime = taskTime;
        }
        String type = VtuzxUtil.getString(param, "type");
        if ("product".equals(type)) {//半成品任务
            try {
                //先创建任务单
                syncKingdeeOrderService.syncPrdOrder(userId, userName, billNo, "pda", taskTime);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
            //传领料
            Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
            String pickBillNo = VtuzxUtil.getString(pickDoc, "billNo");//领料单号
            try {
                syncKingdeeOrderService.syncPrdPickOrder(userId, userName, pickBillNo, "pda", pickTime);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
            //传补料
            List<Document> supplementList = new ArrayList<>();
            Iterator<Document> supplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
            while (supplementItr.hasNext()) {
                Document supplementDoc = supplementItr.next();
                supplementList.add(supplementDoc);
            }
            for (Document supplementDoc : supplementList) {
                String supplementBillNo = VtuzxUtil.getString(supplementDoc, "billNo");
                try {
                    syncKingdeeOrderService.syncPrdReplenishment(userId, userName, supplementBillNo, "pda", supplementTime);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
            }
            //传退料
            Iterator<Document> prdInReturnItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
            List<String> returnNoList = new ArrayList<>();//退料单号
            while (prdInReturnItr.hasNext()) {
                Document prdInReturnDoc = prdInReturnItr.next();
                String returnBillNo = VtuzxUtil.getString(prdInReturnDoc, "billNo");
                returnNoList.add(returnBillNo);
            }
            if (!VtuzxUtil.isEmpty(returnNoList)) {
                for (String returnBillNo : returnNoList) {
                    try {
                        syncKingdeeOrderService.syncReturn(userId, userName, returnBillNo, "pda", returnTime);
                    } catch (Exception e) {
                        _logger.info(e.getMessage());
                    }
                }
            }
            //变品传金蝶
            Iterator<Document> desaltingItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("desalting").is(true), null, 0, 0);
            List<String> desaltingList = new ArrayList<>();//变品退料单号
            while (desaltingItr.hasNext()) {
                Document desaltingDoc = desaltingItr.next();
                String desaltingNo = VtuzxUtil.getString(desaltingDoc, "billNo");
                String materialNo = VtuzxUtil.getString(desaltingDoc, "materialNo");
                desaltingList.add(desaltingNo);
            }
            if (!VtuzxUtil.isEmpty(desaltingList)) {
                int number = 0;//判断是第几次循环
                for (String desaltingBillNo : desaltingList) {
                    try {
                        syncKingdeeOrderService.syncDesaltingInStock(userId, userName, billNo, desaltingBillNo, "pda", desaltingTime, number);
                        number++;
                    } catch (Exception e) {
                        _logger.info(e.getMessage());
                    }
                }
            }
            //传入库
            Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("task").is(true), null, 0, 0);
            List<String> prdInNoList = new ArrayList<>();
            while (prdInItr.hasNext()) {
                Document prdInDoc = prdInItr.next();
                String prdInBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                prdInNoList.add(prdInBillNo);
            }
            for (String prdInNo : prdInNoList) {
                try {
                    syncKingdeeOrderService.syncPrdInStockOrder(userId, userName, prdInNo, "pda", prdInTime);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
            }
        } else {//传分选

            if (checked) {//如果点只传调拨单
                List<Map<String, Object>> boxList = new ArrayList<>();
                List<String> colBillNoList = new ArrayList<>();
                //排除退料
                Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(billNo).and("colType").ne("return"), null, 0, 0);
                while (prdColItr.hasNext()) {
                    Document prdColDoc = prdColItr.next();
                    Map<String, Object> prdColMap = new LinkedHashMap<>(prdColDoc);
                    String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                    colBillNoList.add(colBillNo);
                    boxList.add(prdColMap);
                }
                //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                //把领料和补料的仓库先放到一个集合中
                Map<String, Object> stockMap = new HashMap<>();//k:（领料和补料）物料加批次加仓库,v:document
                Map<String, Object> returnMap = new HashMap<>();//k:物料加批次，v:仓库
                Iterator<Document> bomPickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomPickItr.hasNext()) {
                    Document bomPickDoc = bomPickItr.next();
                    String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    } else {
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        double count = VtuzxUtil.getDouble(bomPickDoc, "count");
                        bomPickDoc.replace("count", returnCount + count);
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    }
                }

                Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomSupplementItr.hasNext()) {
                    Document bomSupplementDoc = bomSupplementItr.next();
                    String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    } else {
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        double count = VtuzxUtil.getDouble(bomSupplementDoc, "count");
                        bomSupplementDoc.replace("count", returnCount + count);
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    }
                }

                List<Document> returnList = new ArrayList<>();//退料需要做调拨的

                Iterator<Document> returnItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
                while (returnItr.hasNext()) {
                    Document returnDoc = returnItr.next();
                    String stockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//说明退料仓库和领料仓库不一致，需要做调拨
                        returnList.add(returnDoc);
                    }
                }

                try {
                    Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
                    String llBillNo = VtuzxUtil.getString(pickDoc, "billNo");
                    //做调拨
                    syncKingdeeOrderService.syncStockTransferOrder(userId, userName, llBillNo, "pda", taskTime);

                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
            } else {//如果没点的话正常传分选
                List<Map<String, Object>> boxList = new ArrayList<>();
                List<String> colBillNoList = new ArrayList<>();
                //排除退料
                Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(billNo).and("colType").ne("return"), null, 0, 0);
                while (prdColItr.hasNext()) {
                    Document prdColDoc = prdColItr.next();
                    Map<String, Object> prdColMap = new LinkedHashMap<>(prdColDoc);
                    String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                    colBillNoList.add(colBillNo);
                    boxList.add(prdColMap);
                }
                //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                //把领料和补料的仓库先放到一个集合中
                Map<String, Object> stockMap = new HashMap<>();//k:（领料和补料）物料加批次加仓库,v:document
                Map<String, Object> returnMap = new HashMap<>();//k:物料加批次，v:仓库
                Iterator<Document> bomPickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomPickItr.hasNext()) {
                    Document bomPickDoc = bomPickItr.next();
                    String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    } else {
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        double count = VtuzxUtil.getDouble(bomPickDoc, "count");
                        bomPickDoc.replace("count", returnCount + count);
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    }
                }

                Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomSupplementItr.hasNext()) {
                    Document bomSupplementDoc = bomSupplementItr.next();
                    String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    } else {
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        double count = VtuzxUtil.getDouble(bomSupplementDoc, "count");
                        bomSupplementDoc.replace("count", returnCount + count);
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    }
                }

                List<Document> returnList = new ArrayList<>();//退料需要做调拨的

                Iterator<Document> returnItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
                while (returnItr.hasNext()) {
                    Document returnDoc = returnItr.next();
                    String stockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//说明退料仓库和领料仓库不一致，需要做调拨
                        returnList.add(returnDoc);
                    }
                }
                try {
                    //做生产订单
                    syncKingdeeOrderService.syncPrdOrderSorting(userId, userName, billNo, "pda", boxList, taskTime);
                    Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
                    String llBillNo = VtuzxUtil.getString(pickDoc, "billNo");
                    //调拨之前查询一下是否有调拨单
                    VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();

                    List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "STK_TransferDirect", new VtuzxArrayList<>(
                                    "FBillNo"

                            ),
                            String.format("F_zjdbd_ZTDJH = '%s'", billNo), null, 0, 0);
                    if (VtuzxUtil.isEmpty(prdOrderQuery)) {
                        //做调拨
                        syncKingdeeOrderService.syncStockTransferOrder(userId, userName, llBillNo, "pda", taskTime);
                    }

                    //做领料
                    syncKingdeeOrderService.syncPrdPickOrderSorting(userId, userName, llBillNo, "pda", boxList, pickTime);
                    //入库
                    List<Document> inList = new ArrayList<>();
                    List<String> inHeaderBillNoList = new ArrayList<>();
                    Iterator<Document> prdInDocItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                    while (prdInDocItr.hasNext()) {
                        Document prdInDoc = prdInDocItr.next();
                        String inHeaderBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                        inHeaderBillNoList.add(inHeaderBillNo);
                    }

                    Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("billNo").in(inHeaderBillNoList), null, 0, 0);
                    while (prdInItr.hasNext()) {
                        inList.add(prdInItr.next());
                    }
                    String inBillNo = VtuzxUtil.getString(inList.get(0), "billNo");
                    syncKingdeeOrderService.syncPrdInStockOrderSorting(userId, userName, inBillNo, "pda", prdInTime);
                    //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                    if (!returnList.isEmpty()) {
                        //判断一下当前订单传没传调拨单
                        syncKingdeeOrderAllocation(userId, userName, returnList, returnMap, billNo, "pda");
                    }

                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
                //修改传单状态
                UpdateResult res = prdTaskDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("isUpload", true)));
                if (res.getModifiedCount() == 0) {
                    throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
                }
            }


        }

        return null;
    }

    //手动传单BN
    @Override
    public VtuzxMap uploadKingdeeTaskBn(ObjectId userId, String userName, Map<String, Object> param) throws Exception {
        // 获取param中的billNo
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 获取param中的taskTime
        String taskTime = VtuzxUtil.getString(param, "taskTime");
        // 获取param中的createTime
        String createTime = VtuzxUtil.getString(param, "createTime");
        // 获取createTime的前10位
        String subTime = createTime.substring(0, 10);
        // 获取param中的checked
        Boolean checked = VtuzxUtil.getBoolean(param, "checked");
        // 获取param中的pickTime
        String pickTime = VtuzxUtil.getString(param, "pickTime");
        Boolean uploadFlag = false;
        // 如果任务时间不是"Invalid Date"，并且领料时间不是"Invalid Date"，则将领料时间设置为任务时间
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(pickTime)) {
            pickTime = taskTime;
        }
        // 获取补料时间
        String supplementTime = VtuzxUtil.getString(param, "supplementTime");//补料
        // 如果任务时间不是"Invalid Date"，并且补料时间不是"Invalid Date"，则将补料时间设置为任务时间
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(supplementTime)) {
            supplementTime = taskTime;
        }
        // 获取退料时间
        String returnTime = VtuzxUtil.getString(param, "returnTime");//退料
        // 如果任务时间不是"Invalid Date"，并且退料时间不是"Invalid Date"，则将退料时间设置为任务时间
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(returnTime)) {
            returnTime = taskTime;
        }
        // 获取变品退料时间
        String desaltingTime = VtuzxUtil.getString(param, "desaltingTime");//变品退料
        // 如果任务时间不是"Invalid Date"，并且变品退料时间不是"Invalid Date"，则将变品退料时间设置为任务时间
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(desaltingTime)) {
            desaltingTime = taskTime;
        }
        // 获取入库时间
        String prdInTime = VtuzxUtil.getString(param, "prdInTime");//入库
        // 如果任务时间不是"Invalid Date"，并且入库时间不是"Invalid Date"，则将入库时间设置为任务时间
        if (!"Invalid Date".equals(taskTime) && "Invalid Date".equals(prdInTime)) {
            prdInTime = taskTime;
        }
        String type = VtuzxUtil.getString(param, "type");
        if ("product".equals(type)) {//半成品任务
            try {
                //先创建任务单
                syncKingdeeOrderService.syncPrdOrderBn(userId, userName, billNo, "pda", taskTime);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
            //根据任务单号查询领料单
            Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
            //获取领料单号
            String pickBillNo = VtuzxUtil.getString(pickDoc, "billNo");
            try {
                //调用同步金蝶领料单服务
                uploadFlag = syncKingdeeOrderService.syncPrdPickOrderBn(userId, userName, billNo, pickBillNo, "pda", pickTime, uploadFlag);
            } catch (Exception e) {
                //记录异常信息
                _logger.info(e.getMessage());
            }
            if(!uploadFlag) {
                //传补料
                // 创建一个空的List，用于存储补料单据
                List<Document> supplementList = new ArrayList<>();
                // 根据billNo查询补料单据
                Iterator<Document> supplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                // 遍历补料单据
                while (supplementItr.hasNext()) {
                    // 获取补料单据
                    Document supplementDoc = supplementItr.next();
                    // 将补料单据添加到List中
                    supplementList.add(supplementDoc);
                }
                // 遍历补料单据List
                /*for (Document supplementDoc : supplementList) {
                    // 获取补料单据的单据编号
                    String supplementBillNo = VtuzxUtil.getString(supplementDoc, "billNo");
                    try {
                        // 调用同步金蝶订单服务，同步补料单据
                        syncKingdeeOrderService.syncPrdReplenishmentBn(userId, userName, supplementBillNo, "pda", supplementTime);
                    } catch (Exception e) {
                        // 捕获异常并打印日志
                        _logger.info(e.getMessage());
                    }
                }*/
                //补料单调整：合并多个补料单中的物料，只需传一次补料
                try {
                    //调用同步金蝶订单服务，同步补料单据
                    syncKingdeeOrderService.syncPrdReplenishmentBn(userId, userName, supplementList, "pda", supplementTime);
                } catch (Exception e) {
                    // 捕获异常并打印日志
                    _logger.info(e.getMessage());
                }
            }
            //根据退料单号查询退料单列表
            Iterator<Document> prdInReturnItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
            //创建退料单号列表
            List<String> returnNoList = new ArrayList<>();//退料单号
            //遍历退料单列表
            while (prdInReturnItr.hasNext()) {
                //获取退料单
                Document prdInReturnDoc = prdInReturnItr.next();
                //获取退料单号
                String returnBillNo = VtuzxUtil.getString(prdInReturnDoc, "billNo");
                //将退料单号添加到列表中
                returnNoList.add(returnBillNo);
            }
            // 判断returnNoList是否为空
            if (!VtuzxUtil.isEmpty(returnNoList)) {
                // 遍历returnNoList
                for (String returnBillNo : returnNoList) {
                    try {
                        // 调用syncKingdeeOrderService的syncReturnBn方法，传入userId, userName, returnBillNo, "pda", returnTime参数
                        syncKingdeeOrderService.syncReturnBn(userId, userName, returnBillNo, "pda", returnTime);
                    } catch (Exception e) {
                        // 捕获异常，并记录日志
                        _logger.info(e.getMessage());
                    }
                }
            }
            //变品传金蝶
            Iterator<Document> desaltingItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("desalting").is(true), null, 0, 0);
            List<String> desaltingList = new ArrayList<>();//变品退料单号
            while (desaltingItr.hasNext()) {
                Document desaltingDoc = desaltingItr.next();
                String desaltingNo = VtuzxUtil.getString(desaltingDoc, "billNo");
                String materialNo = VtuzxUtil.getString(desaltingDoc, "materialNo");
                //取出明细中批次是BN的
                Document desaltingInDetailDoc = prdInDetailDao.findOne(Criteria.where("billNo").is(desaltingNo));
                String batchNo = VtuzxUtil.getString(desaltingInDetailDoc, "batchNo");
                if(batchNo.startsWith("BN")) {
                    desaltingList.add(desaltingNo);
                }
            }
            if (!VtuzxUtil.isEmpty(desaltingList)) {
                int number = 0;//判断是第几次循环
                for (String desaltingBillNo : desaltingList) {
                    try {
                        syncKingdeeOrderService.syncDesaltingInStockBn(userId, userName, billNo, desaltingBillNo, "pda", desaltingTime, number);
                        number++;
                    } catch (Exception e) {
                        _logger.info(e.getMessage());
                    }
                }
            }
            // 根据条件查询符合条件的Document集合，并获取迭代器
            Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("task").is(true), null, 0, 0);
            // 创建一个List，用于存储符合条件的Document的billNo
            List<String> prdInNoList = new ArrayList<>();
            // 遍历迭代器，将符合条件的Document的billNo添加到List中
            // 遍历prdInItr
            while (prdInItr.hasNext()) {
                // 获取下一个文档
                Document prdInDoc = prdInItr.next();
                // 从文档中获取billNo字段的值
                String prdInBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                // 将billNo的值添加到prdInNoList中
                prdInNoList.add(prdInBillNo);
            }
            // 遍历prdInNoList列表
            for (String prdInNo : prdInNoList) {
                try {
                    // 调用syncKingdeeOrderService的syncPrdInStockOrderBn方法，传入userId、userName、prdInNo、"pda"、prdInTime参数
                    syncKingdeeOrderService.syncPrdInStockOrderBn(userId, userName, prdInNo, "pda", prdInTime);
                } catch (Exception e) {
                    // 捕获异常，并打印异常信息
                    _logger.info(e.getMessage());
                }
            }
        } else {//传分选
            // 如果checked为true
            if (checked) {
                // 创建一个List，用于存储boxList
                List<Map<String, Object>> boxList = new ArrayList<>();
                // 创建一个List，用于存储colBillNoList
                List<String> colBillNoList = new ArrayList<>();
                //排除退料
                // 查询prdColDao中taskBillNo为billNo且colType不为return的记录
                Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(billNo).and("colType").ne("return"), null, 0, 0);
                // 遍历查询结果
                while (prdColItr.hasNext()) {
                    // 获取记录
                    Document prdColDoc = prdColItr.next();
                    // 将记录转换为Map
                    Map<String, Object> prdColMap = new LinkedHashMap<>(prdColDoc);
                    // 获取billNo字段值
                    String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                    // 将billNo字段值添加到colBillNoList中
                    colBillNoList.add(colBillNo);
                    // 将prdColMap添加到boxList中
                    boxList.add(prdColMap);
                }
                //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                //把领料和补料的仓库先放到一个集合中
                Map<String, Object> stockMap = new HashMap<>();//k:（领料和补料）物料加批次加仓库,v:document
                Map<String, Object> returnMap = new HashMap<>();//k:物料加批次，v:仓库
                // 获取物料领料明细列表
                Iterator<Document> bomPickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomPickItr.hasNext()) {
                    // 获取物料领料明细文档
                    Document bomPickDoc = bomPickItr.next();
                    // 获取库存编号
                    String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                    // 获取物料编号
                    String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                    // 获取批次号
                    String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
                    // 根据物料编号、批次号和库存编号获取库存文档
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    // 将物料编号和批次号作为key，库存编号作为value存入returnMap中
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    } else {
                        // 获取退库单中的数量
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        // 获取领料单中的数量
                        double count = VtuzxUtil.getDouble(bomPickDoc, "count");
                        // 将两个数量相加，替换领料单中的数量
                        bomPickDoc.replace("count", returnCount + count);
                        // 将修改后的领料单放入库存映射表中
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    }
                }
                //根据条件查询bomSupplementDetail表中的数据
                Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                //遍历查询结果
                while (bomSupplementItr.hasNext()) {
                    //获取bomSupplementDetail表中的一条数据
                    Document bomSupplementDoc = bomSupplementItr.next();
                    //获取stockNo、materialNo、batchNo字段的数据
                    String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
                    //从stockMap中获取对应的数据
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    //将materialNo和batchNo作为key，stockNo作为value存入returnMap
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    } else {
                        // 获取退库单中的数量
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        // 获取补料单中的数量
                        double count = VtuzxUtil.getDouble(bomSupplementDoc, "count");
                        // 将退库单中的数量和补料单中的数量相加
                        bomSupplementDoc.replace("count", returnCount + count);
                        // 将新的补料单放入库存映射中
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    }
                }
                List<Document> returnList = new ArrayList<>();//退料需要做调拨的
                //根据taskBillNo和return字段查询prdInDetailDao，返回一个迭代器
                Iterator<Document> returnItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
                //遍历迭代器
                while (returnItr.hasNext()) {
                    //获取下一个文档
                    Document returnDoc = returnItr.next();
                    //获取stockNo、materialNo和batchNo字段的值
                    String stockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    //从stockMap中获取materialNo、batchNo和stockNo对应的文档
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//说明退料仓库和领料仓库不一致，需要做调拨
                        returnList.add(returnDoc);
                    }
                }
                try {
                    //根据任务单号查询对应的单据
                    Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
                    //获取单据号
                    String llBillNo = VtuzxUtil.getString(pickDoc, "billNo");
                    //做调拨
                    syncKingdeeOrderService.syncStockTransferOrderBn(userId, userName, llBillNo, "pda", taskTime);
                } catch (Exception e) {
                    //记录异常信息
                    _logger.info(e.getMessage());
                }
            } else {//如果没点的话正常传分选
                //创建一个空的List，用于存储分选信息
                List<Map<String, Object>> boxList = new ArrayList<>();
                //创建一个空的List，用于存储分选单号
                List<String> colBillNoList = new ArrayList<>();
                //排除退料
                //从prdColDao中查找符合条件的分选信息，并返回一个Iterator
                Iterator<Document> prdColItr = prdColDao.findList(Criteria.where("taskBillNo").is(billNo).and("colType").ne("return"), null, 0, 0);
                //遍历Iterator
                while (prdColItr.hasNext()) {
                    //获取下一个分选信息
                    Document prdColDoc = prdColItr.next();
                    //将分选信息转换为Map
                    Map<String, Object> prdColMap = new LinkedHashMap<>(prdColDoc);
                    //获取分选单号
                    String colBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
                    //将分选单号添加到List中
                    colBillNoList.add(colBillNo);
                    //将分选信息添加到List中
                    boxList.add(prdColMap);
                }
                //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                //把领料和补料的仓库先放到一个集合中
                Map<String, Object> stockMap = new HashMap<>();//k:（领料和补料）物料加批次加仓库,v:document
                Map<String, Object> returnMap = new HashMap<>();//k:物料加批次，v:仓库
                Iterator<Document> bomPickItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                while (bomPickItr.hasNext()) {
                    // 获取下一个BOM领料单
                    Document bomPickDoc = bomPickItr.next();
                    // 获取库存编号
                    String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                    // 获取物料编号
                    String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                    // 获取批次号
                    String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
                    // 根据物料编号、批次号和库存编号从stockMap中获取对应的Document
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    // 将物料编号和批次号作为key，库存编号作为value存入returnMap
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    } else {
                        // 获取退料单中的数量
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        // 获取领料单中的数量
                        double count = VtuzxUtil.getDouble(bomPickDoc, "count");
                        // 将退料单中的数量和领料单中的数量相加，并替换领料单中的数量
                        bomPickDoc.replace("count", returnCount + count);
                        // 将更新后的领料单放入stockMap中
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                    }
                }
                // 查找与billNo匹配的物料补充明细
                Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                // 遍历查询结果
                while (bomSupplementItr.hasNext()) {
                    // 获取下一个物料补充明细
                    Document bomSupplementDoc = bomSupplementItr.next();
                    // 获取物料补充明细中的库存编号
                    String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                    // 获取物料补充明细中的物料编号
                    String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                    // 获取物料补充明细中的批次号
                    String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
                    // 从stockMap中获取与物料编号、批次号、库存编号匹配的Document
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    // 将物料编号和批次号作为key，库存编号作为value存入returnMap中
                    returnMap.put(materialNo + "_" + batchNo, stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//如果map集合中还没有数据
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    } else {
                        // 获取退料单中的数量
                        double returnCount = VtuzxUtil.getDouble(returnDocument, "count");
                        // 获取补料单中的数量
                        double count = VtuzxUtil.getDouble(bomSupplementDoc, "count");
                        // 将退料单中的数量和补料单中的数量相加，替换补料单中的数量
                        bomSupplementDoc.replace("count", returnCount + count);
                        // 将补料单放入库存映射中
                        stockMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                    }
                }
                List<Document> returnList = new ArrayList<>();//退料需要做调拨的
                Iterator<Document> returnItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
                while (returnItr.hasNext()) {
                    //遍历退料仓库的文档
                    Document returnDoc = returnItr.next();
                    //获取退料的stockNo、materialNo、batchNo
                    String stockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    String materialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String batchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    //根据退料的materialNo、batchNo、stockNo从stockMap中获取对应的退料文档
                    Document returnDocument = (Document) stockMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                    if (VtuzxUtil.isEmpty(returnDocument)) {//说明退料仓库和领料仓库不一致，需要做调拨
                        returnList.add(returnDoc);
                    }
                }
                try {
                    //做生产订单
                    syncKingdeeOrderService.syncPrdOrderSortingBn(userId, userName, billNo, "pda", boxList, taskTime);
                    Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(billNo));
                    String llBillNo = VtuzxUtil.getString(pickDoc, "billNo");
                    //调拨之前查询一下是否有调拨单
                    VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYeXiang();
                    List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "STK_TransferDirect", new VtuzxArrayList<>(
                                    "FBillNo"
                            ),
                            String.format("F_zjdbd_ZTDJH = '%s'", billNo), null, 0, 0);
                    if (VtuzxUtil.isEmpty(prdOrderQuery)) {
                        //做调拨
                        syncKingdeeOrderService.syncStockTransferOrderBn(userId, userName, llBillNo, "pda", taskTime);
                    }
                    //做领料
                    syncKingdeeOrderService.syncPrdPickOrderSortingBn(userId, userName, llBillNo, "pda", boxList, pickTime);
                    //入库
                    List<Document> inList = new ArrayList<>();
                    List<String> inHeaderBillNoList = new ArrayList<>();
                    Iterator<Document> prdInDocItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
                    while (prdInDocItr.hasNext()) {
                        Document prdInDoc = prdInDocItr.next();
                        String inHeaderBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                        inHeaderBillNoList.add(inHeaderBillNo);
                    }
                    Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("billNo").in(inHeaderBillNoList), null, 0, 0);
                    while (prdInItr.hasNext()) {
                        inList.add(prdInItr.next());
                    }
                    String inBillNo = VtuzxUtil.getString(inList.get(0), "billNo");
                    syncKingdeeOrderService.syncPrdInStockOrderSortingBn(userId, userName, inBillNo, "pda", prdInTime);
                    //如果退料的仓库和领料或者补料的仓库不一致的话需要做调拨单
                    if (!returnList.isEmpty()) {
                        //判断一下当前订单传没传调拨单
                        syncKingdeeOrderAllocation(userId, userName, returnList, returnMap, billNo, "pda");
                    }
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
                //修改传单状态
                UpdateResult res = prdTaskDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("isUpload", true)));
                if (res.getModifiedCount() == 0) {
                    throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
                }
            }
        }
        return null;
    }

    @Override
    public VtuzxMap updatePrdType(ObjectId userId, String name, List<String> billNoList) throws VtuzxException {
        for (String billNo : billNoList) {
            UpdateResult res = prdTaskDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("status", "audit")));
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
        }
        return null;
    }

    @Override
    public VtuzxMap updatePrdBusinessStatus(ObjectId userId, String name, List<String> billNoList) throws VtuzxException {
        for (String billNo : billNoList) {
            UpdateResult res = prdTaskDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$set", new Document("businessStatus", "start")));
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
        }
        return null;
    }

    /**
     * 添加领料箱子的实际重量
     *
     * @param userId
     * @param userName
     * @param param
     * @return
     */
    @Override
    public VtuzxMap changeMaterialBomActual(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        _logger.info(String.format("实际重量修改人:%s", userName));
        String billNo = VtuzxUtil.getString(param, "billNo");
        double actualCount = VtuzxUtil.getDouble(param, "actualCount");
        UpdateResult updateResult = materialBomPickDao.updateOne(Criteria.where("billNo").is(billNo), new Document("actualCount", actualCount));
        if (updateResult.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return null;
    }

    @Override
    public VtuzxMap changeSupplimentBomActual(ObjectId userId, String userName, Map<String, Object> param) throws VtuzxException {
        _logger.info(String.format("实际重量修改人:%s", userName));
        String billNo = VtuzxUtil.getString(param, "billNo");
        double actualCount = VtuzxUtil.getDouble(param, "actualCount");
        UpdateResult updateResult = materialBomSupplementDao.updateOne(Criteria.where("billNo").is(billNo), new Document("actualCount", actualCount));
        if (updateResult.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return null;
    }

    @Override
    public VtuzxDownloadBean downloadPrdTaskList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String type = VtuzxUtil.getString(param, "type");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String produceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        String isUpload = VtuzxUtil.getString(param, "isUpload");
        String status = VtuzxUtil.getString(param, "status");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        if (!VtuzxUtil.isEmpty(isUpload)) {
            boolean isUploadBoo = Boolean.parseBoolean(isUpload);
            cond.and("isUpload").is(isUploadBoo);
        }

        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("type").is(type);
        }
        if (!VtuzxUtil.isEmpty(produceHouseName)) {
            cond.and("produceHouseName").is(produceHouseName);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(materialNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            Map<String, Object> taskMap = new HashMap<>();
            Iterator<Document> materialBomPickDetailItr = prdTaskDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                taskMap.put(pickBillNo, materialBomPickDetailDoc);
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }

            List<VtuzxMap> pickList = new ArrayList<>();

            Iterator<Document> materialBomPickItr = prdTaskDao.findList(cond.and("billNo").in(pickBillNoList), null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            for (VtuzxMap data : pickList) {
                String taskBillNo = VtuzxUtil.getString(data, "billNo");
                Document detailDoc = VtuzxUtil.getObject(taskMap, taskBillNo);
                String detailMaterialNo = VtuzxUtil.getString(detailDoc, "materialNo");
                String detailMaterialName = VtuzxUtil.getString(detailDoc, "materialName");
                String detailMaterialModel = VtuzxUtil.getString(detailDoc, "materialModel");
                double count = VtuzxUtil.getDouble(detailDoc, "count");
                data.append("materialNo", detailMaterialNo)
                        .append("materialName", detailMaterialName)
                        .append("materialModel", detailMaterialModel)
                        .append("count", count);
            }
            String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

            List<VtuzxExcelSheet> sheets = new ArrayList<>();
            VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "生产任务");
            int col = 0;
            int row = 0;
            VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, "单据编号"),
                    new VtuzxExcelCell(col++, "生产车间"),
                    new VtuzxExcelCell(col++, "创建时间"),
                    new VtuzxExcelCell(col++, "创建人"),
                    new VtuzxExcelCell(col++, "物料编码"),
                    new VtuzxExcelCell(col++, "物料名称"),
                    new VtuzxExcelCell(col++, "物料规格"),
                    new VtuzxExcelCell(col++, "数量")
            ));
            sheet0.addRow(header0);
            for (VtuzxMap detail : pickList) {
                col = 0;
                VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                        new VtuzxExcelCell(col++, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())
                ));
                sheet0.addRow(dataRow);
            }

            sheet0.setColumnWidth(new VtuzxArrayList<>(
                    new int[]{0, 200},
                    new int[]{1, 200},
                    new int[]{2, 200},
                    new int[]{3, 300},
                    new int[]{4, 200},
                    new int[]{5, 200},
                    new int[]{7, 150},
                    new int[]{8, 80}
            ));

            sheets.add(sheet0);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            VtuzxExcel.write(stream, sheets);
            return new VtuzxDownloadBean("生产任务" + timestamp + ".xlsx", stream);
        }
        List<String> taskBillNoList = new ArrayList<>();
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> {
            VtuzxMap data = new VtuzxMap(doc);
            String prdStatus = VtuzxUtil.getString(data, "status");
            if ("audit".equals(prdStatus)) {
                data.replace("status", "审核");
            } else if ("save".equals(prdStatus)) {
                data.replace("status", "保存");
            } else {
                data.replace("status", "关闭");
            }
            String businessStatus = VtuzxUtil.getString(data, "businessStatus");
            if ("start".equals(businessStatus)) {
                data.replace("businessStatus", "开工");
            } else if ("release".equals(businessStatus)) {
                data.replace("businessStatus", "下达");
            } else {
                data.replace("businessStatus", "完工");
            }
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            taskBillNoList.add(taskBillNo);
            data.append("id", VtuzxUtil.removeString(data, "_id"));
            data.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "createTime")));
            data.append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "auditTime")));
            return data;
        });

        Criteria detailCond = new Criteria();
        Map<String, Object> taskMap = new HashMap<>();//key :任务号 val ：详情信息
        Iterator<Document> taskDetailItr = prdTaskDetailDao.findList(detailCond.and("billNo").in(taskBillNoList), null, 0, 0);
        while (taskDetailItr.hasNext()) {
            Document detailDoc = taskDetailItr.next();
            String taskBillNo = VtuzxUtil.getString(detailDoc, "billNo");
            taskMap.put(taskBillNo, detailDoc);
        }
        //添加内层表数据
        for (VtuzxMap data : dataList) {
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            Document detailDoc = VtuzxUtil.getObject(taskMap, taskBillNo);
            String detailMaterialNo = VtuzxUtil.getString(detailDoc, "materialNo");
            String detailMaterialName = VtuzxUtil.getString(detailDoc, "materialName");
            String detailMaterialModel = VtuzxUtil.getString(detailDoc, "materialModel");
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            data.append("materialNo", detailMaterialNo)
                    .append("materialName", detailMaterialName)
                    .append("materialModel", detailMaterialModel)
                    .append("count", count);
        }

        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "生产任务");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "序号"),
                new VtuzxExcelCell(col++, "状态"),
                new VtuzxExcelCell(col++, "单据编号"),
                new VtuzxExcelCell(col++, "单据类型"),
                new VtuzxExcelCell(col++, "生产车间"),
                new VtuzxExcelCell(col++, "数量"),
                new VtuzxExcelCell(col++, "业务状态"),
                new VtuzxExcelCell(col++, "领料状态"),
                new VtuzxExcelCell(col++, "备注"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col++, "创建人"),
                new VtuzxExcelCell(col++, "物料编码"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "物料规格"),
                new VtuzxExcelCell(col++, "数量")
        ));
        sheet0.addRow(header0);
        int i = 0;
        for (VtuzxMap detail : dataList) {
            i++;
            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, i),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "status")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "type").equals("sorting") ? "分选" : "半成品、产成品"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getDouble(detail, "count")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "businessStatus")),//业务状态
                    new VtuzxExcelCell(col++, VtuzxUtil.getBoolean(detail, "pickStatus") ? "已领料" : "未领料"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "remark")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                    new VtuzxExcelCell(col++, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 200},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 200},
                new int[]{7, 200},
                new int[]{8, 300},
                new int[]{9, 200},
                new int[]{10, 200},
                new int[]{11, 150},
                new int[]{12, 80},
                new int[]{13, 80}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("生产任务" + timestamp + ".xlsx", stream);
    }

    @Override
    public VtuzxDownloadBean downloadPrdTaskListBn(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String type = VtuzxUtil.getString(param, "type");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String produceHouseName = VtuzxUtil.getString(param, "produceHouseName");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        String isUpload = VtuzxUtil.getString(param, "isUpload");
        String status = VtuzxUtil.getString(param, "status");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        if (!VtuzxUtil.isEmpty(isUpload)) {
            boolean isUploadBoo = Boolean.parseBoolean(isUpload);
            cond.and("isUpload").is(isUploadBoo);
        }

        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("type").is(type);
        }
        if (!VtuzxUtil.isEmpty(produceHouseName)) {
            cond.and("produceHouseName").is(produceHouseName);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        //BN批次过滤
        Set<String> bnTaskBillNos = new HashSet<>();
        {
            //领料单处理
            Criteria detailBatchCriteria = Criteria.where("batchNo").regex("^BN");
            Iterator<Document> bnDetailItr = materialBomPickDetailDao.findList(detailBatchCriteria, null, 0, 0);
            Set<String> pickBillNos = new HashSet<>();
            while (bnDetailItr.hasNext()) {
                Document doc = bnDetailItr.next();
                pickBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            if (!pickBillNos.isEmpty()) {
                Iterator<Document> pickBillItr = materialBomPickDao.findList(Criteria.where("billNo").in(pickBillNos), null, 0, 0);
                while (pickBillItr.hasNext()) {
                    Document doc = pickBillItr.next();
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
            //补料单处理
            Criteria suppBatchCriteria = Criteria.where("batchNo").regex("^BN");
            Iterator<Document> bnSuppDetailItr = materialBomSupplementDetailDao.findList(suppBatchCriteria, null, 0, 0);
            Set<String> suppBillNos = new HashSet<>();
            while (bnSuppDetailItr.hasNext()) {
                Document doc = bnSuppDetailItr.next();
                suppBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            if (!suppBillNos.isEmpty()) {
                Iterator<Document> suppBillItr = materialBomSupplementDao.findList(Criteria.where("billNo").in(suppBillNos), null, 0, 0);
                while (suppBillItr.hasNext()) {
                    Document doc = suppBillItr.next();
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
            //入库单处理
            Criteria inBatchCriteria = Criteria.where("batchNo").regex("^BN");
            Iterator<Document> bnInDetailItr = prdInDetailDao.findList(inBatchCriteria, null, 0, 0);
            Set<String> inBillNos = new HashSet<>();
            while (bnInDetailItr.hasNext()) {
                Document doc = bnInDetailItr.next();
                inBillNos.add(VtuzxUtil.getString(doc, "billNo"));
            }
            if (!inBillNos.isEmpty()) {
                Iterator<Document> inBillItr = prdInDao.findList(Criteria.where("billNo").in(inBillNos), null, 0, 0);
                while (inBillItr.hasNext()) {
                    Document doc = inBillItr.next();
                    bnTaskBillNos.add(VtuzxUtil.getString(doc, "taskBillNo"));
                }
            }
        }
        //如果BN过滤后无数据则返回空Excel
        if (bnTaskBillNos.isEmpty()) {
            String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());
            List<VtuzxExcelSheet> sheets = new ArrayList<>();
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            VtuzxExcel.write(stream, sheets);
            return new VtuzxDownloadBean("生产任务BN" + timestamp + ".xlsx", stream);
        }
        //将BN过滤条件添加到主查询条件
        cond.and("billNo").in(bnTaskBillNos);
        if (!VtuzxUtil.isEmpty(materialNo) && VtuzxUtil.isEmpty(billNo)) {
            List<String> pickBillNoList = new ArrayList<>();
            Criteria pickCond = new Criteria();
            if (!VtuzxUtil.isEmpty(materialNo)) {
                pickCond.and("materialNo").is(materialNo);
            }
            Map<String, Object> taskMap = new HashMap<>();
            Iterator<Document> materialBomPickDetailItr = prdTaskDetailDao.findList(pickCond, null, 0, 0);
            while (materialBomPickDetailItr.hasNext()) {
                Document materialBomPickDetailDoc = materialBomPickDetailItr.next();
                String pickBillNo = VtuzxUtil.getString(materialBomPickDetailDoc, "billNo");
                taskMap.put(pickBillNo, materialBomPickDetailDoc);
                if (!pickBillNoList.contains(pickBillNo)) {
                    pickBillNoList.add(pickBillNo);
                }
            }
            List<VtuzxMap> pickList = new ArrayList<>();
            Iterator<Document> materialBomPickItr = prdTaskDao.findList(cond.and("billNo").in(pickBillNoList), null, pageIndex, pageSize);
            while (materialBomPickItr.hasNext()) {
                Document materialBomPickDoc = materialBomPickItr.next();
                VtuzxMap materialBomPickMap = new VtuzxMap(materialBomPickDoc);
                materialBomPickMap.append("id", VtuzxUtil.getString(materialBomPickMap, IVtuzxConst.Key__id));
                materialBomPickMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPickMap, "createTime")));
                pickList.add(materialBomPickMap);
            }
            for (VtuzxMap data : pickList) {
                String taskBillNo = VtuzxUtil.getString(data, "billNo");
                Document detailDoc = VtuzxUtil.getObject(taskMap, taskBillNo);
                String detailMaterialNo = VtuzxUtil.getString(detailDoc, "materialNo");
                String detailMaterialName = VtuzxUtil.getString(detailDoc, "materialName");
                String detailMaterialModel = VtuzxUtil.getString(detailDoc, "materialModel");
                double count = VtuzxUtil.getDouble(detailDoc, "count");
                data.append("materialNo", detailMaterialNo)
                        .append("materialName", detailMaterialName)
                        .append("materialModel", detailMaterialModel)
                        .append("count", count);
            }
            String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

            List<VtuzxExcelSheet> sheets = new ArrayList<>();
            VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "生产任务BN");
            int col = 0;
            int row = 0;
            VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, "单据编号"),
                    new VtuzxExcelCell(col++, "生产车间"),
                    new VtuzxExcelCell(col++, "创建时间"),
                    new VtuzxExcelCell(col++, "创建人"),
                    new VtuzxExcelCell(col++, "物料编码"),
                    new VtuzxExcelCell(col++, "物料名称"),
                    new VtuzxExcelCell(col++, "物料规格"),
                    new VtuzxExcelCell(col++, "数量")
            ));
            sheet0.addRow(header0);
            for (VtuzxMap detail : pickList) {
                col = 0;
                VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                        new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                        new VtuzxExcelCell(col++, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())
                ));
                sheet0.addRow(dataRow);
            }
            sheet0.setColumnWidth(new VtuzxArrayList<>(
                    new int[]{0, 200},
                    new int[]{1, 200},
                    new int[]{2, 200},
                    new int[]{3, 300},
                    new int[]{4, 200},
                    new int[]{5, 200},
                    new int[]{7, 150},
                    new int[]{8, 80}
            ));
            sheets.add(sheet0);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            VtuzxExcel.write(stream, sheets);
            return new VtuzxDownloadBean("生产任务BN" + timestamp + ".xlsx", stream);
        }
        List<String> taskBillNoList = new ArrayList<>();
        VtuzxPage page = prdTaskDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> {
            VtuzxMap data = new VtuzxMap(doc);
            String prdStatus = VtuzxUtil.getString(data, "status");
            if ("audit".equals(prdStatus)) {
                data.replace("status", "审核");
            } else if ("save".equals(prdStatus)) {
                data.replace("status", "保存");
            } else {
                data.replace("status", "关闭");
            }
            String businessStatus = VtuzxUtil.getString(data, "businessStatus");
            if ("start".equals(businessStatus)) {
                data.replace("businessStatus", "开工");
            } else if ("release".equals(businessStatus)) {
                data.replace("businessStatus", "下达");
            } else {
                data.replace("businessStatus", "完工");
            }
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            taskBillNoList.add(taskBillNo);
            data.append("id", VtuzxUtil.removeString(data, "_id"));
            data.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "createTime")));
            data.append("auditTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.removeObject(data, "auditTime")));
            return data;
        });
        Criteria detailCond = new Criteria();
        Map<String, Object> taskMap = new HashMap<>();//key :任务号 val ：详情信息
        Iterator<Document> taskDetailItr = prdTaskDetailDao.findList(detailCond.and("billNo").in(taskBillNoList), null, 0, 0);
        while (taskDetailItr.hasNext()) {
            Document detailDoc = taskDetailItr.next();
            String taskBillNo = VtuzxUtil.getString(detailDoc, "billNo");
            taskMap.put(taskBillNo, detailDoc);
        }
        //添加内层表数据
        for (VtuzxMap data : dataList) {
            String taskBillNo = VtuzxUtil.getString(data, "billNo");
            Document detailDoc = VtuzxUtil.getObject(taskMap, taskBillNo);
            String detailMaterialNo = VtuzxUtil.getString(detailDoc, "materialNo");
            String detailMaterialName = VtuzxUtil.getString(detailDoc, "materialName");
            String detailMaterialModel = VtuzxUtil.getString(detailDoc, "materialModel");
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            data.append("materialNo", detailMaterialNo)
                    .append("materialName", detailMaterialName)
                    .append("materialModel", detailMaterialModel)
                    .append("count", count);
        }

        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "生产任务BN");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "序号"),
                new VtuzxExcelCell(col++, "状态"),
                new VtuzxExcelCell(col++, "单据编号"),
                new VtuzxExcelCell(col++, "单据类型"),
                new VtuzxExcelCell(col++, "生产车间"),
                new VtuzxExcelCell(col++, "数量"),
                new VtuzxExcelCell(col++, "业务状态"),
                new VtuzxExcelCell(col++, "领料状态"),
                new VtuzxExcelCell(col++, "备注"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col++, "创建人"),
                new VtuzxExcelCell(col++, "物料编码"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "物料规格"),
                new VtuzxExcelCell(col++, "数量")
        ));
        sheet0.addRow(header0);
        int i = 0;
        for (VtuzxMap detail : dataList) {
            i++;
            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, i),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "status")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "type").equals("sorting") ? "分选" : "半成品、产成品"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getDouble(detail, "count")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "businessStatus")),//业务状态
                    new VtuzxExcelCell(col++, VtuzxUtil.getBoolean(detail, "pickStatus") ? "已领料" : "未领料"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "remark")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                    new VtuzxExcelCell(col++, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 200},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 200},
                new int[]{7, 200},
                new int[]{8, 300},
                new int[]{9, 200},
                new int[]{10, 200},
                new int[]{11, 150},
                new int[]{12, 80},
                new int[]{13, 80}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("生产任务BN" + timestamp + ".xlsx", stream);
    }

    //车间收货新增一箱
    private VtuzxMap addNewBox(ObjectId userId, String name, Map<String, Object> box, String seialNo, int index, String taskBillNo, String produceHouseName) throws InterruptedException {

//        String id = VtuzxUtil.getString(box,"id");
        String materialNo = VtuzxUtil.getString(box, "materialNo");
        String materialName = VtuzxUtil.getString(box, "materialName");
        String materialModel = VtuzxUtil.getString(box, "materialModel");
        String supplierNo = VtuzxUtil.getString(box, "supplierNo");
        String supplierName = VtuzxUtil.getString(box, "supplierName");
        int standard = VtuzxUtil.getInt(box, "standard");
        String unit = VtuzxUtil.getString(box, "unit");
        String unitName = VtuzxUtil.getString(box, "unitName");
        String department = VtuzxUtil.getString(box, "department");
        String batchNo = VtuzxUtil.getString(box, "batchNo");

        int orderNum = 0;
        if ("干参包装车间".equals(produceHouseName)) {//判断排序方式
            double orderCount = prdColDetailDao.count(Criteria.where("taskBillNo").is(taskBillNo).and("isTemp").ne(true));
            orderNum = (int) orderCount + index + 2;
        } else {
            orderNum = index + 2;
        }

        double traceCount = VtuzxUtil.getDouble(box, "traceCount");//追溯重量
        List<String> traceBack = new ArrayList<>();
        traceBack.add(seialNo);
        Thread.sleep(10);
        String boxNo = "A02" + new Date().getTime();
        Document updateDoc = new Document("materialNo", materialNo)
                .append("materialModel", materialModel)
                .append("materialName", materialName)
                .append("supplierNo", supplierNo)
                .append("supplierName", supplierName)
                .append("unit", unit)
                .append("unitName", unitName)
                .append("boxNo", boxNo)
                .append("batchNo", batchNo)
                .append("count", 1)
                .append("inStock", false)
                .append("comment", "")
                .append("_insertUserId", userId)
                .append("insertUserName", name)
                .append("isTemp", true)
                .append("noPrint", true)
                .append("taskBillNo", taskBillNo)
                .append("department", department)
                .append("standard", standard)
                .append("isDelete", true)
                .append("currentCount", 1)
                .append("traceCount", traceCount)
                .append("orderNum", String.format("%04d", orderNum))
                .append("traceBack", traceBack);

        prdColDetailDao.insertOne(updateDoc);

        return new VtuzxMap(updateDoc);
    }

    //传吉客云唯一码,(一次上传不能超过两千)
    private void createSerial(Document storeDoc, List<String> allTraceBack, String materialNo, String materialModel) {
        //如果数量大于1000分开传
        if (allTraceBack.size() > 1000) {
            List<String> lastTraceBack = allTraceBack.subList(0, 1000);
            List<String> endTraceBack = allTraceBack.subList(1000, allTraceBack.size());//剩下的追溯码
            String stringFromList = String.join(",", lastTraceBack);//把唯一码转化成Str类型
            VtuzxMap bizcontent = new VtuzxMap();//业务请求参数
            bizcontent.append("goodsNo", materialNo)
                    .append("skuName", materialModel)
                    .append("serialNoList", stringFromList)
                    .append("snDefine2", VtuzxUtil.formatYmdHmsF(new Date()))//生产日期
                    .append("snDefine1", VtuzxUtil.formatYmdHmsF(new Date()));//入库日期
            System.out.println("传前1000个");
            try {
                iJiKeYunApiService.serialNoAdd(storeDoc, bizcontent);
            } catch (Exception e) {
                _logger.info("唯一码未上传的原因" + e.getMessage());
            }
            createSerial(storeDoc, endTraceBack, materialNo, materialModel);
        } else {//否则一次性传
            String stringFromList = String.join(",", allTraceBack);//把唯一码转化成Str类型
            VtuzxMap bizcontent = new VtuzxMap();//业务请求参数
            bizcontent.append("goodsNo", materialNo)
                    .append("skuName", materialModel)
                    .append("serialNoList", stringFromList)
                    .append("snDefine2", VtuzxUtil.formatYmdHmsF(new Date()))//生产日期
                    .append("snDefine1", VtuzxUtil.formatYmdHmsF(new Date()));//入库日期
            System.out.println("最后不到一千全传完");
            try {
                iJiKeYunApiService.serialNoAdd(storeDoc, bizcontent);
            } catch (Exception e) {
                _logger.info("唯一码未上传的原因" + e.getMessage());
            }
            return;
        }
    }

    private void syncKingdeeOrderAllocation(ObjectId userId, String userName, List<Document> returnList, Map<String, Object> stockMap, String billNo, String source) throws Exception {
        if (returnList.size() == 0) {
            throw new VtuzxException("不存在分录,请确认订单是否正确!");
        }
        Map<String, Object> stockTransferModel = new LinkedHashMap<>();
        Map<String, Object> stockTransferParam = new LinkedHashMap<>();
        List<Map<String, Object>> stockTransferEntryList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        for (Document prdPick : returnList) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            materialNoList.add(materialNo);
        }

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }

        String pickCreateTime = "";
        for (Document prdPick : returnList) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(prdPick, "batchNo");
            String stockNo = (String) stockMap.get(materialNo + "_" + batchNo);
            String toStockNo = VtuzxUtil.getString(prdPick, "stockNo");
            String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPick, "createTime"));
            double count = VtuzxUtil.getDouble(prdPick, "count");
            pickCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPick, "createTime"));

            Map<String, Object> stockTransferEntry = new LinkedHashMap<>();
            stockTransferEntry.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            stockTransferEntry.put("FUnitID", new VtuzxMap("FNumber", unit));
            stockTransferEntry.put("FQty", count);
            stockTransferEntry.put("FLot", new VtuzxMap("FNumber", batchNo));
            stockTransferEntry.put("FSrcStockId", new VtuzxMap("FNumber", stockNo));
            stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", toStockNo));
            stockTransferEntry.put("FSrcStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            stockTransferEntry.put("FDestStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            stockTransferEntry.put("FBusinessDate", createTime);
            stockTransferEntry.put("FOwnerTypeOutId", "BD_OwnerOrg");
            stockTransferEntry.put("FOwnerOutId", new VtuzxMap("FNumber", "100"));
            stockTransferEntry.put("FOwnerTypeId", "BD_OwnerOrg");
            stockTransferEntry.put("FOwnerId", new VtuzxMap("FNumber", "100"));
            stockTransferEntry.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            stockTransferEntry.put("FBaseQty", count);
            stockTransferEntry.put("FISFREE", false);
            stockTransferEntry.put("FKeeperTypeId", "BD_KeeperOrg");
            stockTransferEntry.put("FKeeperId", new VtuzxMap("FNumber", "100"));
            stockTransferEntry.put("FKeeperTypeOutId", "BD_KeeperOrg");
            stockTransferEntry.put("FKeeperOutId", new VtuzxMap("FNumber", "100"));
            stockTransferEntry.put("FDestLot", new VtuzxMap("FNumber", batchNo));
            stockTransferEntry.put("FDestMaterialId", new VtuzxMap("FNumber", materialNo));
            stockTransferEntry.put("FSaleUnitId", new VtuzxMap("FNumber", unit));
            stockTransferEntry.put("FSaleQty", count);
            stockTransferEntry.put("FSalBaseQty", count);
            stockTransferEntry.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
            stockTransferEntry.put("FPriceQty", count);
            stockTransferEntry.put("FPriceBaseQty", count);
            stockTransferEntry.put("FTransReserveLink", false);
            stockTransferEntry.put("FCheckDelivery", false);
            stockTransferEntryList.add(stockTransferEntry);
        }

        stockTransferModel.put("FBillTypeID", new VtuzxMap("FNumber", "ZJDB01_SYS"));
        stockTransferModel.put("FBizType", "NORMAL");
        stockTransferModel.put("FTransferDirect", "GENERAL");
        stockTransferModel.put("FTransferBizType", "InnerOrgTransfer");
        stockTransferModel.put("FSettleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FSaleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOutOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FOwnerTypeOutIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FOwnerOutIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FIsIncludedTax", true);
        stockTransferModel.put("FIsPriceExcludeTax", true);
        stockTransferModel.put("FExchangeTypeId", new VtuzxMap("FNumber", "HLTX01_SYS"));
        stockTransferModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FSETTLECURRID", new VtuzxMap("FNumber", "PRE001"));
        stockTransferModel.put("FExchangeRate", 1.0);
        stockTransferModel.put("FOwnerIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FDate", pickCreateTime);
        stockTransferModel.put("FBaseCurrId", new VtuzxMap("FNumber", "PRE001"));
        stockTransferModel.put("F_zjdbd_ZTDJH", billNo);
        stockTransferModel.put("F_zjdbd_CZRY", userName);
        stockTransferModel.put("F_zjdbd_FHR", userName);
        stockTransferModel.put("F_zjdbd_SJLY", source);
        stockTransferModel.put("F_zjdbd_ZTYWRQ", pickCreateTime);
        stockTransferModel.put("FBillEntry", stockTransferEntryList);

        stockTransferParam.put("Model", stockTransferModel);

        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        List<VtuzxMap> transferList = kingdeeService.save(client, "STK_TransferDirect", stockTransferParam);
        VtuzxMap transferMap = transferList.get(0);
        String number = VtuzxUtil.getString(transferMap, "Number");
        kingdeeService.submit(client, "STK_TransferDirect", "0", number);
        kingdeeService.audit(client, "STK_TransferDirect", "0", number, "STK_InvCheckResult");

    }
//    @Override
//    public VtuzxMap createMaterialBomPickBillSpecial(ObjectId userId, String userName, Map<String, Object> param) throws Exception {
//        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
//        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
//        String billNo = IXqcConst.createBillNo(BillType.SCLL);
//
//
//        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
//        Document prdTaskDetail = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
//        String materialNo = VtuzxUtil.getString(prdTaskDetail,"materialNo");//分选任务生产的物料编号
//        String materialName = VtuzxUtil.getString(prdTaskDetail,"materialName");
//        String unit = VtuzxUtil.getString(prdTaskDetail,"unit");
//
//        String type = VtuzxUtil.getString(prdTaskDoc,"type");
//        if(type.equals("product")){
//            throw new VtuzxException("半成品，成品无法创建");
//        }
//        double colCount = VtuzxUtil.getDouble(prdTaskDetail,"count");
//        String produceHouseName = VtuzxUtil.getString(prdTaskDoc,"produceHouseName");
//        String produceHouseNo = VtuzxUtil.getString(prdTaskDoc,"produceHouseNo");
//        String startTime = VtuzxUtil.getObject(prdTaskDoc,"startTime");
//        String endTime = VtuzxUtil.getObject(prdTaskDoc,"endTime");
//        //先从生产任务单(detail)里查询物料规格
//        Document prdTaskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
//        String materialModel = VtuzxUtil.getString(prdTaskDetailDoc,"materialModel");
//        //如果规格是混并且任务类型是分选就跑一遍生产(手动添加分选的领料信息)
//
//            //先调用用料清单
//            VtuzxMap taskParam = new VtuzxMap();//用料清单参数
//            VtuzxMap dataMap = new VtuzxMap();
//            //去bom表里查询需要的数据
//            List<Document> dataList = new ArrayList<>();
//            Document bomDoc = bomDao.findOne(Criteria.where("materialNo").is(materialNo));
//            bomDoc.append("count",colCount);
//            dataList.add(bomDoc);
//            //往参数里添加数据
//            dataMap.append("dataList",dataList)
//                    .append("produceHouseName",produceHouseName)
//                    .append("produceHouse",produceHouseNo)
//                    .append("startTime",startTime)
//                    .append("endTime",endTime)
//                    .append("taskType","product")
//                    .append("sort",5);
//            taskParam.append("dataMap",dataMap);
//            //用料清单
//            VtuzxMap materialList = taskBillToMaterialList(userId,userName,taskParam);
//            //创建生产任务
//            VtuzxMap colParam = new VtuzxMap();//创建生产任务参数
//            colParam.append("taskList",dataMap)
//                    .append("materialList",VtuzxUtil.getObject(materialList,"materialList"))
//                    .append("taskType","product")
//                    .append("sort",5);
//            createPrdTaskBill(userId,userName,colParam);
//            //审核生产任务
//            //先获取生产任务编号
//            Document productPrdColDoc = prdTaskDao.findOne(Criteria.where("startTime").is(startTime).and("type").is("product"));
//            String productBillNo = VtuzxUtil.getString(productPrdColDoc,"billNo");
//            VtuzxMap auditParam = new VtuzxMap("billNo",productBillNo);
//            //调用审核生产任务单
//            auditPrdTaskBill(userId,userName,auditParam);
//            //创建半成品领料单,先调用addMaterialBomBox方法
//            List<String> stockNoLists = new ArrayList<>();
//            List<VtuzxMap> pickBoxList = new ArrayList<>();
//            Iterator<Document> materialBoxItr = materialBomPickDetailBoxDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
//            while (materialBoxItr.hasNext()){
//                Document materialBoxDoc = materialBoxItr.next();
//                String materialStockNo = VtuzxUtil.getString(materialBoxDoc,"stockNo");
//                VtuzxMap pickMap = new VtuzxMap(materialBoxDoc);
//                pickBoxList.add(pickMap);
//                stockNoLists.add(materialStockNo);
//            }
//            String stockNo = "";
//            if (stockNoLists != null && stockNoLists.size()>0){
//                 stockNo = stockNoLists.get(0);
//            }
//            List<String> _idList = new ArrayList<>();//存放要删除的id
//            Iterator<Document> pickDetailItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
//
//            while (pickDetailItr.hasNext()){
//                Document pickDetailDoc = pickDetailItr.next();
//                String _id = VtuzxUtil.getString(pickDetailDoc,"_id");
//                _idList.add(_id);
//
//            }
////            materialBomPickDetailDao.deleteMany(Criteria.where("taskBillNo").is(taskBillNo));
////            materialBomPickDetailBoxDao.deleteMany(Criteria.where("taskBillNo").is(taskBillNo));
//            //先删除现有的分选任务领料
//
//            Document materialBoxDoc = materialBomPickDetailBoxDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
//            String locationNo = VtuzxUtil.getString(materialBoxDoc,"locationNo");
//            Document materialDoc = materialBomDao.findOne(Criteria.where("taskBillNo").is(productBillNo));
//
//            for (String _id:_idList){
//                produceService.deleteUserMaterialBomPickMaterial(userId,_id);//删除现有的领料
//            }
//
//            //循环pickBoxList循环几次添加几次物料
//            for (VtuzxMap addMap:pickBoxList){
//                String batchNo = VtuzxUtil.getString(addMap,"batchNo");
//                String addMaterialNo = VtuzxUtil.getString(addMap,"materialNo");
//                //从即时库存表查询需要补充的数据参数
//                Document inventoryDoc = inventoryDao.findOne(Criteria.where("batchNo").is(batchNo).and("materialNo").is(addMaterialNo));
//                addMap.append("barcodeType",VtuzxUtil.getString(inventoryDoc,"barcodeType"))
//                        .append("produceDate",VtuzxUtil.getObject(inventoryDoc,"produceDate"))
//                        .append("exp",VtuzxUtil.getString(inventoryDoc,"exp"))
//                        .append("inStockTime",VtuzxUtil.getObject(inventoryDoc,"produceDate"));
//
//                VtuzxMap addParam = new VtuzxMap("stockNo",stockNo)
//                        .append("billNo","")
//                        .append("taskBillNo",productBillNo)
//                        .append("materialBomBillNo",VtuzxUtil.getString(materialDoc,"billNo"));
//                List<VtuzxMap> addList = new ArrayList<>();
//                addList.add(addMap);
//                addParam.append("boxList",addList);
//                produceService.addMaterialBomBox(userId,userName,addParam);
//            }
//
//            //调用生产领料单
//            VtuzxMap pickParam = new VtuzxMap();
//            pickParam.append("stockNo",stockNo)
//                    .append("taskBillNo",productBillNo)
//                    .append("produceHouse",produceHouseName);
//            VtuzxMap materialBomPickBill = produceService.createMaterialBomPickBill(userId, userName, pickParam);
//            String scllBillNo = VtuzxUtil.getString(materialBomPickBill,"billNo");
//            Document materialBomDoc = materialBomDao.findOne(Criteria.where("taskBillNo").is(productBillNo));
//            String materialBomBillNo = VtuzxUtil.getString(materialBomDoc,"billNo");
//
//
//            VtuzxMap auditPickParam = new VtuzxMap();//领料单审核参数
//            auditPickParam.append("stockNo",stockNo)
//                    .append("billNo",scllBillNo)
//                    .append("materialBomBillNo",materialBomBillNo)
//                    .append("taskBillNo",productBillNo);
//            //调用领料单审核
//            produceService.auditMaterialBomPickBill(userId,userName,auditPickParam);
//            //做半成品savePrdTaskToPrdCol车间收货
//            List<VtuzxMap> boxList = new ArrayList<>();
//            List<String> traceBack = new ArrayList<>();
//            VtuzxMap boxMap = new VtuzxMap();
//            boxMap.append("materialName",materialName)
//                    .append("materialModel",materialModel)
//                    .append("materialNo",materialNo)
//                    .append("unitName",unit)
//                    .append("billNo",productBillNo)
//                    .append("batchNo","22222")//先默认一个批次
//                    .append("count",colCount)
//                    .append("traceBack",traceBack)
//                    .append("isDelete",false)
//                    .append("standard",0)
//                    .append("currentCount",0);
//            boxList.add(boxMap);
//            VtuzxMap saveColParam = new VtuzxMap("boxList",boxList);//车间收货参数
//            produceService.saveTaskAddPrdCol(userId,userName,saveColParam);
//            produceService.savePrdTaskToPrdCol(userId,userName,productBillNo,null);
//            //审核生产任务车间收货，先获取车间收货单号
//            Document prdCol = prdColDao.findOne(Criteria.where("taskBillNo").is(productBillNo));
//            String cjshBillNo = VtuzxUtil.getString(prdCol,"billNo");
//            produceService.auditPrdColBill(userId,userName,cjshBillNo);
//            //调用生产任务入库方法，先调用添加物料箱码方法
//            Document prdColDetail = prdColDetailDao.findOne(Criteria.where("taskBillNo").is(productBillNo));
//            List<Map<String, Object>> addList = new ArrayList<>();
//            VtuzxMap addMap = new VtuzxMap();//调用添加箱码方法所需要的参数
//            addMap.append("standard",VtuzxUtil.getDouble(prdColDetail,"standard"))
//                    .append("materialModel",VtuzxUtil.getString(prdCol,"materialSpec"))
//                    .append("materialNo",VtuzxUtil.getString(prdCol,"materialNo"))
//                    .append("remark",VtuzxUtil.getString(prdCol,"remark"))
//                    .append("colType",VtuzxUtil.getString(prdCol,"colType"))
//                    .append("currentCount",VtuzxUtil.getDouble(prdColDetail,"currentCount"))
//                    .append("noPrint",VtuzxUtil.getBoolean(prdColDetail,"noPrint"))
//                    .append("_insertUserId",null)
//                    .append("inStock",VtuzxUtil.getBoolean(prdColDetail,"inStock"))
//                    .append("countTotal",VtuzxUtil.getDouble(prdColDetail,"count"))
//                    .append("department","")
//                    .append("_auditUserId",null)
//                    .append("billNo",VtuzxUtil.getString(prdCol,"billNo"))
//                    .append("prdCount",VtuzxUtil.getDouble(prdCol,"count"))
//                    .append("supplierName","")
//                    .append("res",true)
//                    .append("batchNo",VtuzxUtil.getString(prdCol,"batchNo"))
//                    .append("supplierBatchNo","")
//                    .append("unitName",VtuzxUtil.getString(prdCol,"unit"))
//                    .append("isDelete",false)
//                    .append("materialSpec",VtuzxUtil.getString(prdCol,"materialSpec"))
//                    .append("count",VtuzxUtil.getDouble(prdCol,"count"))
//                    .append("supplierNo",null)
//                    .append("isPrint","unseal")
//                    .append("traceBack",VtuzxUtil.getObject(prdColDetail,"traceBack"))
//                    .append("materialName",VtuzxUtil.getString(prdCol,"materialName"))
//                    .append("unit",VtuzxUtil.getString(prdCol,"unit"))
//                    .append("boxCount",1)
//                    .append("boxNo",VtuzxUtil.getString(prdColDetail,"boxNo"))
//                    .append("insertUserName",userName)
//                    .append("comment","")
//                    .append("taskBillNo",productBillNo)
//                    .append("status","audit");
//            addList.add(addMap);
//            //任务入库添加物料的方法
//            produceService.addPrdInBoxList(userId,userName,addList,stockNo,"YL2002",productBillNo);
//            produceService.createPrdInBill(userId,userName,productBillNo,stockNo);
//            //审核后分选领料的信息变成半成品车间收货的物料信息
//            //删除分选领料信息
//            materialBomPickDao.deleteOne(Criteria.where("taskBillNo").is(taskBillNo));
//            //创建新的分选领料
//            //先调用添加物料的方法
//            List<VtuzxMap> colBoxList = new ArrayList<>();
//            VtuzxMap colMap = new VtuzxMap();
//            //前面先调方法
//            Document prdColDoc = prdColDetailDao.findOne(Criteria.where("taskBillNo").is(productBillNo));
//            colMap.append("batchNo",VtuzxUtil.getString(prdColDoc,"batchNo"))
//                    .append("materialNo",VtuzxUtil.getString(prdColDoc,"materialNo"))
//                    .append("materialName",VtuzxUtil.getString(prdColDoc,"materialName"))
//                    .append("materialSpec",VtuzxUtil.getString(prdColDoc,"materialModel"))
//                    .append("count",VtuzxUtil.getDouble(prdColDoc,"count"))
//                    .append("unit",VtuzxUtil.getString(prdColDoc,"unitName"))
//                    .append("boxNo",VtuzxUtil.getString(prdColDoc,"boxNo"))
//                    .append("produceDate","")
//                    .append("exp",0)
//                    .append("inStockTime",startTime)
//                    .append("locationNo",locationNo)
//                    .append("barcodeType","")
//                    .append("stockNo",stockNo);
//            colBoxList.add(colMap);
//            Document materialBom = materialBomDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
//            VtuzxMap boxParam = new VtuzxMap("stockNo",stockNo);//添加物料的参数
//            boxParam.append("boxList",colBoxList)
//                    .append("taskBillNo",taskBillNo)
//                    .append("billNo","")
//                    .append("materialBomBillNo",VtuzxUtil.getString(materialBom,"billNo"));
//            //调用添加物料的方法
//            addMaterialBomBox(userId,userName,boxParam);
//
//            //自动完成领料
//            String taskUserName = "";
//            ObjectId taskUserId = null;
//            if (prdTaskDoc != null) {
//                taskUserName = VtuzxUtil.getString(prdTaskDoc, "createUserName");
//                taskUserId = VtuzxUtil.getObject(prdTaskDoc, "_createUserId");
//            }
//
//            int sumBoxCount = 1;//新的分选任务领料只有一个箱数
//            Document pickBoxDoc = materialBomPickDetailBoxDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
//            double sumCount =  VtuzxUtil.getDouble(pickBoxDoc,"count");

    /// /            String pickStockNo = VtuzxUtil.getString(pickBoxDoc,"stockNo");
//
//            materialBomPickDao.insertBill(userId, userName,
//                    new Document("billNo", billNo)
//                            .append("taskBillNo", taskBillNo)
//                            .append("status", BillStatus.Save.toString())
//                            .append("boxCount", sumBoxCount)
//                            .append("count", sumCount)
//                            .append("produceHouse", produceHouse)
//                            .append("stockNo",stockNo)
//                            .append("taskUserName", taskUserName)
//                            .append("taskUserId", taskUserId)
//                            .append("isPrint","unseal"));
//
//            try {
//                Document detailUpdateVal = new Document("$set", new Document("billNo", billNo).append("status", "save"));
//                detailUpdateVal.append("$unset", new Document("isTemp", 1));
//                materialBomPickDetailDao.updateManyRedirect(Criteria.where("taskBillNo").is(taskBillNo), detailUpdateVal);
//                materialBomPickDetailBoxDao.updateManyRedirect(Criteria.where("taskBillNo").is(taskBillNo), detailUpdateVal);
//            } catch (Exception e) {
//
//                Criteria rollbackCond = Criteria.where("billNo").is(billNo);
//                materialBomPickDetailDao.updateManyRedirect(rollbackCond,
//                        new Document("$set", new Document("status", "save")));
//                materialBomPickDetailBoxDao.updateManyRedirect(rollbackCond,
//                        new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
//                throw e;
//            }
//
//            return new VtuzxMap("billNo", billNo);
//
//    }
    public VtuzxDownloadBean downloadBean(List<Document> dataList, String type) throws Exception {
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, type);
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "状态"),
                new VtuzxExcelCell(col++, "单据编号"),
                new VtuzxExcelCell(col++, "生产任务号"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col++, "生产车间"),
                new VtuzxExcelCell(col++, "仓库"),
                new VtuzxExcelCell(col++, "仓位"),
                new VtuzxExcelCell(col++, "物料编码"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "物料规格"),
                new VtuzxExcelCell(col++, "单位"),
                new VtuzxExcelCell(col++, "供应商编码"),
                new VtuzxExcelCell(col++, "供应商名称"),
                new VtuzxExcelCell(col++, "批次"),
                new VtuzxExcelCell(col++, "箱数"),
                new VtuzxExcelCell(col, "重量")
        ));
        sheet0.addRow(header0);

        for (Document detail : dataList) {

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "status")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "taskBillNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.formatYmdHmF(VtuzxUtil.getObject(detail, "createTime"))),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "produceHouseName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "stockName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "locationNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "materialSpec")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "unit")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "supplierNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "supplierName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "batchNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "boxCount")),
                    new VtuzxExcelCell(col++, new BigDecimal(VtuzxUtil.getString(detail, "count")).setScale(2, RoundingMode.HALF_UP).doubleValue())
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{1, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 300},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 150},
                new int[]{7, 150},
                new int[]{8, 80}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean(type + timestamp + ".xlsx", stream);
    }

    /**
     * 导出生产领料单
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadMaterialPickList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").is(isPrint);
        }
        List<Document> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Map<String, Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Map<String, Object> houseMap = new HashMap<>();//key;单据编号  value:车间
        Iterator<Document> pickItr = materialBomPickDao.findList(cond, new Document("createTime", -1), 0, 0);
        while (pickItr.hasNext()) {
            Document pickDoc = pickItr.next();
            String pickBillNo = VtuzxUtil.getString(pickDoc, "billNo");
            String status = VtuzxUtil.getString(pickDoc, "status");
            String produceHouseName = VtuzxUtil.getString(pickDoc, "produceHouse");
            if (!billNoList.contains(pickBillNo)) {
                billNoList.add(pickBillNo);
            }
            if ("audit".equals(status)) {
                statusMap.put(pickBillNo, "审核");
            } else {
                statusMap.put(pickBillNo, "保存");
            }
            houseMap.put(pickBillNo, produceHouseName);
        }
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> pickDetailItr = materialBomPickDetailDao.findList(Criteria.where("billNo").in(billNoList), new Document("createTime", -1), 0, 0);
        while (pickDetailItr.hasNext()) {
            Document pickDetailDoc = pickDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(pickDetailDoc, "stockNo");
            dataList.add(pickDetailDoc);
            if (!stockNoList.contains(detailStockNo)) {
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList) {
            String otherStockNo = VtuzxUtil.getString(otherDoc, "stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc, "billNo");
            String stockName = VtuzxUtil.getString(stockMap, otherStockNo);//仓库名称
            String status = VtuzxUtil.getString(statusMap, otherBillNo);//状态
            String produceHouseName = VtuzxUtil.getString(houseMap, otherBillNo);//车间
            otherDoc.append("stockName", stockName);
            otherDoc.append("status", status);
            otherDoc.append("produceHouseName", produceHouseName);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "生产领料");
        return vtuzxDownloadBean;
    }

    @Override
    public VtuzxDownloadBean downloadMaterialSupplimentList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialBomBillNo = VtuzxUtil.getString(param, "materialBomBillNo");
        String produceHouse = VtuzxUtil.getString(param, "produceHouse");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        String taskBillNo = VtuzxUtil.getObject(param, "taskBillNo");
        String isPrint = VtuzxUtil.getString(param, "isPrint");
        Criteria cond = new Criteria();
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(materialBomBillNo)) {
            cond.and("materialBomBillNo").regex(materialBomBillNo);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(produceHouse)) {
            cond.and("produceHouse").regex(produceHouse);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(isPrint)) {
            cond.and("isPrint").regex(isPrint);
        }
        List<Document> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Map<String, Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Map<String, Object> houseMap = new HashMap<>();//key;单据编号  value:车间
        Iterator<Document> supplimentItr = materialBomSupplementDao.findList(cond, new Document("createTime", -1), 0, 0);
        while (supplimentItr.hasNext()) {
            Document supplimentDoc = supplimentItr.next();
            String pickBillNo = VtuzxUtil.getString(supplimentDoc, "billNo");
            String status = VtuzxUtil.getString(supplimentDoc, "status");
            String produceHouseName = VtuzxUtil.getString(supplimentDoc, "produceHouse");
            if (!billNoList.contains(pickBillNo)) {
                billNoList.add(pickBillNo);
            }
            if ("audit".equals(status)) {
                statusMap.put(pickBillNo, "审核");
            } else {
                statusMap.put(pickBillNo, "保存");
            }
            houseMap.put(pickBillNo, produceHouseName);
        }
        //查询补料单详情
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> pickDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").in(billNoList), new Document("createTime", -1), 0, 0);
        while (pickDetailItr.hasNext()) {
            Document pickDetailDoc = pickDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(pickDetailDoc, "stockNo");
            dataList.add(pickDetailDoc);
            if (!stockNoList.contains(detailStockNo)) {
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList) {
            String otherStockNo = VtuzxUtil.getString(otherDoc, "stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc, "billNo");
            String stockName = VtuzxUtil.getString(stockMap, otherStockNo);//仓库名称
            String status = VtuzxUtil.getString(statusMap, otherBillNo);//状态
            String produceHouseName = VtuzxUtil.getString(houseMap, otherBillNo);//状态
            otherDoc.append("stockName", stockName);
            otherDoc.append("status", status);
            otherDoc.append("produceHouseName", produceHouseName);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "生产补料");
        return vtuzxDownloadBean;

    }

    /**
     * 导出领料入库单
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPrdInList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("task").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }

        List<Document> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Map<String, Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Map<String, Object> houseMap = new HashMap<>();//key;单据编号  value:车间
        Map<String,Object> taskMap = new HashMap<>();//key;单据编号  value:生产订单号(详情表里有一些没有生产订单号)
        Iterator<Document> prdInItr = prdInDao.findList(cond, new Document("createTime", -1), 0, 0);
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String pickBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            String status = VtuzxUtil.getString(prdInDoc, "status");
            String produceHouseName = VtuzxUtil.getString(prdInDoc, "produceHouseName");
            String taskBillNoPick = VtuzxUtil.getString(prdInDoc,"taskBillNo");
            if (!billNoList.contains(pickBillNo)) {
                billNoList.add(pickBillNo);
            }
            if ("audit".equals(status)) {
                statusMap.put(pickBillNo, "审核");
            } else {
                statusMap.put(pickBillNo, "保存");
            }
            taskMap.put(pickBillNo,taskBillNoPick);
            houseMap.put(pickBillNo, produceHouseName);
        }
        //查询补料单详情
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> pickDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList), new Document("createTime", -1), 0, 0);
        while (pickDetailItr.hasNext()) {
            Document pickDetailDoc = pickDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(pickDetailDoc, "stockNo");
            dataList.add(pickDetailDoc);
            if (!stockNoList.contains(detailStockNo)) {
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList) {
            String otherStockNo = VtuzxUtil.getString(otherDoc, "stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc, "billNo");
            String stockName = VtuzxUtil.getString(stockMap, otherStockNo);//仓库名称
            String status = VtuzxUtil.getString(statusMap, otherBillNo);//状态
            String taskBillNoDetail = VtuzxUtil.getString(taskMap,otherBillNo);//生产订单号
            String produceHouseName = VtuzxUtil.getString(houseMap, otherBillNo);//状态
            otherDoc.append("stockName", stockName);
            otherDoc.append("taskBillNo",taskBillNoDetail);
            otherDoc.append("status", status);
            otherDoc.append("produceHouseName", produceHouseName);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "领料入库");
        return vtuzxDownloadBean;

    }

    /**
     * 导出变品退料入库单
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPrdInDesaltingList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("desalting").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }

        List<Document> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Map<String, Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Map<String, Object> houseMap = new HashMap<>();//key;单据编号  value:车间
        Map<String,Object> taskMap = new HashMap<>();//key;单据编号  value:生产订单号(详情表里有一些没有生产订单号)
        Iterator<Document> prdInItr = prdInDao.findList(cond, new Document("createTime", -1), 0, 0);
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String pickBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            String produceHouseName = VtuzxUtil.getString(prdInDoc, "produceHouseName");
            String status = VtuzxUtil.getString(prdInDoc, "status");
            String taskBillNoPick = VtuzxUtil.getString(prdInDoc,"taskBillNo");
            if (!billNoList.contains(pickBillNo)) {
                billNoList.add(pickBillNo);
            }
            if ("audit".equals(status)) {
                statusMap.put(pickBillNo, "审核");
            } else {
                statusMap.put(pickBillNo, "保存");
            }
            taskMap.put(pickBillNo,taskBillNoPick);
            houseMap.put(pickBillNo, produceHouseName);
        }
        //查询补料单详情
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> pickDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList), new Document("createTime", -1), 0, 0);
        while (pickDetailItr.hasNext()) {
            Document pickDetailDoc = pickDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(pickDetailDoc, "stockNo");
            dataList.add(pickDetailDoc);
            if (!stockNoList.contains(detailStockNo)) {
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList) {
            String otherStockNo = VtuzxUtil.getString(otherDoc, "stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc, "billNo");
            String stockName = VtuzxUtil.getString(stockMap, otherStockNo);//仓库名称
            String status = VtuzxUtil.getString(statusMap, otherBillNo);//状态
            String taskBillNoDetail = VtuzxUtil.getString(taskMap,otherBillNo);//生产订单号
            String produceHouseName = VtuzxUtil.getString(houseMap, otherBillNo);//车间
            otherDoc.append("stockName", stockName);
            otherDoc.append("taskBillNo",taskBillNoDetail);
            otherDoc.append("status", status);
            otherDoc.append("produceHouseName", produceHouseName);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "变品退料入库");
        return vtuzxDownloadBean;
    }

    /**
     * 导出退料入库单
     *
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPrdInReturnList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        String taskBillNo = VtuzxUtil.getString(param, "taskBillNo");
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria("return").is(true);
        cond.and("count").ne(0);//数量等于零的不显示
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(taskBillNo)) {
            cond.and("taskBillNo").regex(taskBillNo);
        }
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }

        List<Document> dataList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        Map<String, Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Map<String, Object> houseMap = new HashMap<>();//key;单据编号  value:车间
        Map<String,Object> taskMap = new HashMap<>();//key;单据编号  value:生产订单号(详情表里有一些没有生产订单号)
        Iterator<Document> prdInItr = prdInDao.findList(cond, new Document("createTime", -1), 0, 0);
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String pickBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            String produceHouseName = VtuzxUtil.getString(prdInDoc, "produceHouseName");
            String status = VtuzxUtil.getString(prdInDoc, "status");
            String taskBillNoPick = VtuzxUtil.getString(prdInDoc,"taskBillNo");
            if (!billNoList.contains(pickBillNo)) {
                billNoList.add(pickBillNo);
            }
            if ("audit".equals(status)) {
                statusMap.put(pickBillNo, "审核");
            } else {
                statusMap.put(pickBillNo, "保存");
            }
            taskMap.put(pickBillNo,taskBillNoPick);
            houseMap.put(pickBillNo, produceHouseName);
        }
        //查询补料单详情
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> pickDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList), new Document("createTime", -1), 0, 0);
        while (pickDetailItr.hasNext()) {
            Document pickDetailDoc = pickDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(pickDetailDoc, "stockNo");
            dataList.add(pickDetailDoc);
            if (!stockNoList.contains(detailStockNo)) {
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList) {
            String otherStockNo = VtuzxUtil.getString(otherDoc, "stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc, "billNo");
            String stockName = VtuzxUtil.getString(stockMap, otherStockNo);//仓库名称
            String taskBillNoDetail = VtuzxUtil.getString(taskMap,otherBillNo);//生产订单号
            String status = VtuzxUtil.getString(statusMap, otherBillNo);//状态
            String produceHouseName = VtuzxUtil.getString(houseMap, otherBillNo);//状态
            otherDoc.append("stockName", stockName);
            otherDoc.append("status", status);
            otherDoc.append("taskBillNo",taskBillNoDetail);
            otherDoc.append("produceHouseName", produceHouseName);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "退料入库");
        return vtuzxDownloadBean;
    }

    @Override
    public void auditPrdTaskBillList(ObjectId userId, String userName, Map<String, Object> param) {
        List<String> billNoList = VtuzxUtil.getObject(param, "billNoList");
        for (String billNo : billNoList) {
            Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
            String type = VtuzxUtil.getString(prdTaskDoc, "type");
            prdTaskDao.audit(userId, userName, billNo);
            prdTaskDao.updateOne(Criteria.where("billNo").is(billNo), new Document("businessStatus", "release"));
            materialBomDao.updateOne(Criteria.where("taskBillNo").is(billNo), new Document("taskStatus", BillStatus.Audit.toString()));
        }

    }

    @Override
    public VtuzxMap checkPrdColIstock(ObjectId userId, String userName, Map<String, Object> param) {
        String billNo = VtuzxUtil.getString(param, "billNo");
        VtuzxMap data = new VtuzxMap();
        Boolean res = true;
        Criteria cond = new Criteria("taskBillNo").is(billNo);
        Iterator<Document> prdColItr = prdColDao.findList(cond, null, 0, 0);
        List<String> billNoList = new ArrayList<>();//车间收货单号集合
        while (prdColItr.hasNext()) {
            Document prdColDoc = prdColItr.next();
            String prdColBillNo = VtuzxUtil.getString(prdColDoc, "billNo");
            if (!billNoList.contains(prdColBillNo)) {
                billNoList.add(prdColBillNo);
            }
        }
        //查询车间收货详情判断是否有没入库的
        Iterator<Document> prdColDetailItr = prdColDetailDao.findList(new Criteria("billNo").in(billNoList), null, 0, 0);
        while (prdColDetailItr.hasNext()) {
            Document prdColDetailDoc = prdColDetailItr.next();
            Boolean inStock = VtuzxUtil.getBoolean(prdColDetailDoc, "inStock");
            if (!inStock) {
                res = false;
            }
        }
        return data.append("data", res);
    }

    @Override
    public VtuzxMap checkPrdTask(ObjectId userId, String userName, Map<String, Object> param) {
        VtuzxMap data = new VtuzxMap();
        Boolean res = false;
        String billNo = VtuzxUtil.getString(param, "billNo");
        Iterator<Document> prdInItr = prdInDao.findList(new Criteria("taskBillNo").is(billNo)
                .and("task").is(true), null, 0, 0);
        List<String> prdInNoList = new ArrayList<>();
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            String prdInBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            if (!prdInNoList.contains(prdInBillNo)) {
                prdInNoList.add(prdInBillNo);
            }
        }
        //判断是否有相同的物料加批次入到不同的仓库
        Map<String, Object> materialMap = new HashMap<>();//key物料加仓库，val:仓库
        Iterator<Document> prdInDetailItr = prdInDetailDao.findList(new Criteria("billNo").in(prdInNoList), null, 0, 0);
        while (prdInDetailItr.hasNext()) {
            Document detailDoc = prdInDetailItr.next();
            String stockNo = VtuzxUtil.getString(detailDoc, "stockNo");
            String materialNo = VtuzxUtil.getString(detailDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(detailDoc, "batchNo");
            String mapStock = VtuzxUtil.getString(materialMap, materialNo + "_" + batchNo);
            if (!VtuzxUtil.isEmpty(mapStock)) {//判断当前物料加批次有没有仓库值
                if (stockNo.equals(mapStock)) {//获取到的仓库和现有的仓库一致
                    materialMap.put(materialNo + "_" + batchNo, stockNo);
                } else {
                    res = true;
                }
            } else {
                materialMap.put(materialNo + "_" + batchNo, stockNo);
            }
        }
        return data.append("data", res);
    }

    @Override
    public VtuzxMap checkPrdColBatch(ObjectId userId, String name, Map<String, Object> param) {
        String taskBillNo = VtuzxUtil.getString(param,"taskBillNo");
//        String batchNo = VtuzxUtil.getString(param,"batchNo");
        VtuzxMap data = new VtuzxMap();
        data.append("bnBom",false)
                .append("notBn",false);

        Iterator<Document> pickDetailItr = materialBomPickDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
        while (pickDetailItr.hasNext()){
            Document pickDetailDoc = pickDetailItr.next();
            String batchNo = VtuzxUtil.getString(pickDetailDoc,"batchNo");
            if (batchNo.startsWith("BN")){
                data.append("bnBom",true);
            } else {
                data.append("notBn",true);
            }
        }
        List<Document> feedDetailList = new ArrayList<>();
        Iterator<Document> feedDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo),null,0,0);
        while (feedDetailItr.hasNext()){
            Document feedDetailDoc = feedDetailItr.next();
            String batchNo = VtuzxUtil.getString(feedDetailDoc,"batchNo");
            if (batchNo.startsWith("BN")){
                data.append("bnBom",true);
            } else {
                data.append("notBn",true);
            }
        }
        return data;
    }

}